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