]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/weapons/throwing.qc
Split throwing and selection into their own files
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / weapons / throwing.qc
1 .float savenextthink;
2 void thrown_wep_think()
3 {
4         self.owner = world;
5         float timeleft = self.savenextthink - time;
6         if(timeleft > 1)
7                 SUB_SetFade(self, self.savenextthink - 1, 1);
8         else if(timeleft > 0)
9                 SUB_SetFade(self, time, timeleft);
10         else
11                 SUB_VanishOrRemove(self);
12 }
13
14 // returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
15 string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
16 {
17         entity oldself, wep;
18         float wa, thisammo, i, j;
19         string s;
20         var .float ammofield;
21
22         wep = spawn();
23
24         setorigin(wep, org);
25         wep.classname = "droppedweapon";
26         wep.velocity = velo;
27         wep.owner = wep.enemy = own;
28         wep.flags |= FL_TOSSED;
29         wep.colormap = own.colormap;
30
31         if(WEPSET_CONTAINS_AW(WEPBIT_SUPERWEAPONS, wpn))
32         {
33                 if(own.items & IT_UNLIMITED_SUPERWEAPONS)
34                 {
35                         wep.superweapons_finished = time + autocvar_g_balance_superweapons_time;
36                 }
37                 else
38                 {
39                         float superweapons = 1;
40                         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
41                                 if(WEPSET_CONTAINS_AW(WEPBIT_SUPERWEAPONS, i))
42                                         if(WEPSET_CONTAINS_EW(own, i))
43                                                 ++superweapons;
44                         if(superweapons <= 1)
45                         {
46                                 wep.superweapons_finished = own.superweapons_finished;
47                                 own.superweapons_finished = 0;
48                         }
49                         else
50                         {
51                                 float timeleft = own.superweapons_finished - time;
52                                 float weptimeleft = timeleft / superweapons;
53                                 wep.superweapons_finished = time + weptimeleft;
54                                 own.superweapons_finished -= weptimeleft;
55                         }
56                 }
57         }
58
59         wa = W_AmmoItemCode(wpn);
60         if(wa == 0)
61         {
62                 oldself = self;
63                 self = wep;
64                 weapon_defaultspawnfunc(wpn);
65                 self = oldself;
66                 if(startitem_failed)
67                         return string_null;
68                 wep.glowmod = own.weaponentity_glowmod;
69                 wep.think = thrown_wep_think;
70                 wep.savenextthink = wep.nextthink;
71                 wep.nextthink = min(wep.nextthink, time + 0.5);
72                 wep.pickup_anyway = TRUE; // these are ALWAYS pickable
73                 return "";
74         }
75         else
76         {
77                 s = "";
78                 oldself = self;
79                 self = wep;
80                 weapon_defaultspawnfunc(wpn);
81                 self = oldself;
82                 if(startitem_failed)
83                         return string_null;
84                 if(doreduce && g_weapon_stay == 2)
85                 {
86                         for(i = 0, j = 1; i < 24; ++i, j *= 2)
87                         {
88                                 if(wa & j)
89                                 {
90                                         ammofield = Item_CounterField(j);
91
92                                         // if our weapon is loaded, give its load back to the player
93                                         if(self.(weapon_load[self.weapon]) > 0)
94                                         {
95                                                 own.ammofield += self.(weapon_load[self.weapon]);
96                                                 self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading
97                                         }
98
99                                         wep.ammofield = 0;
100                                 }
101                         }
102                 }
103                 else if(doreduce)
104                 {
105                         for(i = 0, j = 1; i < 24; ++i, j *= 2)
106                         {
107                                 if(wa & j)
108                                 {
109                                         ammofield = Item_CounterField(j);
110
111                                         // if our weapon is loaded, give its load back to the player
112                                         if(self.(weapon_load[self.weapon]) > 0)
113                                         {
114                                                 own.ammofield += self.(weapon_load[self.weapon]);
115                                                 self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading
116                                         }
117
118                                         thisammo = min(own.ammofield, wep.ammofield);
119                                         wep.ammofield = thisammo;
120                                         own.ammofield -= thisammo;
121                                         s = strcat(s, " and ", ftos(thisammo), " ", Item_CounterFieldName(j));
122                                 }
123                         }
124                         s = substring(s, 5, -1);
125                 }
126                 wep.glowmod = own.weaponentity_glowmod;
127                 wep.think = thrown_wep_think;
128                 wep.savenextthink = wep.nextthink;
129                 wep.nextthink = min(wep.nextthink, time + 0.5);
130                 wep.pickup_anyway = TRUE; // these are ALWAYS pickable
131
132                 return s;
133         }
134 }
135
136 float W_IsWeaponThrowable(float w)
137 {
138         float wa;
139
140         if (!autocvar_g_pickup_items)
141                 return 0;
142         if (g_weaponarena)
143                 return 0;
144         if (g_cts)
145                 return 0;
146         if (g_nexball && w == WEP_GRENADE_LAUNCHER)
147                 return 0;
148     if(w == 0)
149         return 0;
150         
151         wa = W_AmmoItemCode(w);
152         if(WEPSET_CONTAINS_AW(start_weapons, w))
153         {
154                 // start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo)
155                 if(start_items & IT_UNLIMITED_WEAPON_AMMO)
156                         return 0;
157                 if(wa == 0)
158                         return 0;
159         }
160
161         return 1;
162 }
163
164 // toss current weapon
165 void W_ThrowWeapon(vector velo, vector delta, float doreduce)
166 {
167         float w;
168         string a;
169
170         w = self.weapon;
171         if (w == 0)
172                 return; // just in case
173         if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon))
174                 return;
175         if(!autocvar_g_weapon_throwable)
176                 return;
177         if(self.weaponentity.state != WS_READY)
178                 return;
179         if(!W_IsWeaponThrowable(w))
180                 return;
181
182         if(!WEPSET_CONTAINS_EW(self, w))
183                 return;
184         WEPSET_ANDNOT_EW(self, w);
185
186         W_SwitchWeapon_Force(self, w_getbestweapon(self));
187         a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
188         
189         if not(a) return;
190         Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_WEAPON_DROP, a, w);
191 }