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