items.qc 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. /* Copyright (C) 1996-2022 id Software LLC
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  13. See file, 'COPYING', for details.
  14. */
  15. void() W_SetCurrentAmmo;
  16. /* ALL LIGHTS SHOULD BE 0 1 0 IN COLOR ALL OTHER ITEMS SHOULD
  17. BE .8 .3 .4 IN COLOR */
  18. void() SUB_regen =
  19. {
  20. self.model = self.mdl; // restore original model
  21. self.solid = SOLID_TRIGGER; // allow it to be touched again
  22. sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM); // play respawn sound
  23. setorigin (self, self.origin);
  24. };
  25. /*QUAKED noclass (0 0 0) (-8 -8 -8) (8 8 8)
  26. prints a warning message when spawned
  27. */
  28. void() noclass =
  29. {
  30. dprint ("noclass spawned at");
  31. dprint (vtos(self.origin));
  32. dprint ("\n");
  33. remove (self);
  34. };
  35. /*
  36. ============
  37. PlaceItem
  38. plants the object on the floor
  39. ============
  40. */
  41. void() PlaceItem =
  42. {
  43. local float oldz;
  44. if( self.netname == string_null ) {
  45. if( self.items ) {
  46. self.netname = GetNetName( self.items );
  47. } else if( self.weapon ) {
  48. self.netname = GetNetName( self.weapon );
  49. }
  50. }
  51. self.mdl = self.model; // so it can be restored on respawn
  52. self.flags = FL_ITEM; // make extra wide
  53. self.solid = SOLID_TRIGGER;
  54. self.movetype = MOVETYPE_TOSS;
  55. self.velocity = '0 0 0';
  56. self.origin_z = self.origin_z + 6;
  57. oldz = self.origin_z;
  58. if (!droptofloor())
  59. {
  60. dprint ("Bonus item fell out of level at ");
  61. dprint (vtos(self.origin));
  62. dprint ("\n");
  63. remove(self);
  64. return;
  65. }
  66. };
  67. /*
  68. ============
  69. StartItem
  70. Sets the clipping size and plants the object on the floor
  71. ============
  72. */
  73. void() StartItem =
  74. {
  75. self.nextthink = time + 0.2; // items start after other solids
  76. self.think = PlaceItem;
  77. };
  78. /*
  79. =========================================================================
  80. HEALTH BOX
  81. =========================================================================
  82. */
  83. //
  84. // T_Heal: add health to an entity, limiting health to max_health
  85. // "ignore" will ignore max_health limit
  86. //
  87. float (entity e, float healamount, float ignore) T_Heal =
  88. {
  89. if (e.health <= 0)
  90. return 0;
  91. if ((!ignore) && (e.health >= e.max_health))
  92. return 0;
  93. healamount = ceil(healamount);
  94. e.health = e.health + healamount;
  95. if ((!ignore) && (e.health >= e.max_health))
  96. e.health = e.max_health;
  97. if (e.health > 250)
  98. e.health = 250;
  99. return 1;
  100. };
  101. /*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
  102. Health box. Normally gives 25 points.
  103. Rotten box heals 5-10 points,
  104. megahealth will add 100 health, then
  105. rot you down to your maximum health limit,
  106. one point per second.
  107. */
  108. float H_ROTTEN = 1;
  109. float H_MEGA = 2;
  110. .float healamount, healtype;
  111. void() health_touch;
  112. void() item_health =
  113. {
  114. self.touch = health_touch;
  115. if (self.spawnflags & H_ROTTEN)
  116. {
  117. precache_model("maps/b_bh10.bsp");
  118. precache_sound("items/r_item1.wav");
  119. setmodel(self, "maps/b_bh10.bsp");
  120. self.noise = "items/r_item1.wav";
  121. self.healamount = 15;
  122. self.healtype = 0;
  123. }
  124. else if (self.spawnflags & H_MEGA)
  125. {
  126. precache_model("maps/b_bh100.bsp");
  127. precache_sound("items/r_item2.wav");
  128. setmodel(self, "maps/b_bh100.bsp");
  129. self.noise = "items/r_item2.wav";
  130. self.healamount = 100;
  131. self.healtype = 2;
  132. }
  133. else
  134. {
  135. precache_model("maps/b_bh25.bsp");
  136. precache_sound("items/health1.wav");
  137. setmodel(self, "maps/b_bh25.bsp");
  138. self.noise = "items/health1.wav";
  139. self.healamount = 25;
  140. self.healtype = 1;
  141. }
  142. setsize (self, '0 0 0', '32 32 56');
  143. StartItem ();
  144. };
  145. void() health_touch =
  146. {
  147. if (other.classname != "player")
  148. return;
  149. if (self.healtype == 2) // Megahealth? Ignore max_health...
  150. {
  151. if (other.health >= 250)
  152. return;
  153. if (!T_Heal(other, self.healamount, 1))
  154. return;
  155. }
  156. else
  157. {
  158. if (!T_Heal(other, self.healamount, 0))
  159. return;
  160. }
  161. sprint(other, "$qc_item_health", ftos(self.healamount));
  162. // health touch sound
  163. sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  164. stuffcmd (other, "bf\n");
  165. self.model = string_null;
  166. self.solid = SOLID_NOT;
  167. if ( self.healtype == 2 ) { // If we're a MegaHealth - rot down the player's super health
  168. other.items = other.items | IT_SUPERHEALTH;
  169. other.healthrot_nextcheck = time + 5;
  170. }
  171. if ( deathmatch && deathmatch != 2 ) { // deathmatch 2 is silly old rules
  172. if ( self.healtype == 2 ) {
  173. self.nextthink = time + 120;
  174. } else {
  175. self.nextthink = time + 20;
  176. }
  177. }
  178. self.think = SUB_regen;
  179. activator = other;
  180. SUB_UseTargets(); // fire all targets / killtargets
  181. };
  182. /*
  183. ===============================================================================
  184. ARMOR
  185. ===============================================================================
  186. */
  187. void() armor_touch =
  188. {
  189. local float type, value, bit;
  190. type = 0.3;
  191. value = 100;
  192. bit = IT_ARMOR1;
  193. if (other.health <= 0)
  194. return;
  195. if (other.classname != "player")
  196. return;
  197. if (self.classname == "item_armor1")
  198. {
  199. type = 0.3;
  200. value = 100;
  201. bit = IT_ARMOR1;
  202. }
  203. if (self.classname == "item_armor2")
  204. {
  205. type = 0.6;
  206. value = 150;
  207. bit = IT_ARMOR2;
  208. }
  209. if (self.classname == "item_armorInv")
  210. {
  211. type = 0.8;
  212. value = 200;
  213. bit = IT_ARMOR3;
  214. }
  215. if (other.armortype*other.armorvalue >= type*value)
  216. return;
  217. other.armortype = type;
  218. other.armorvalue = value;
  219. other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
  220. self.solid = SOLID_NOT;
  221. self.model = string_null;
  222. if (deathmatch && deathmatch != 2)
  223. self.nextthink = time + 20;
  224. self.think = SUB_regen;
  225. sprint(other, "$qc_item_armor");
  226. // armor touch sound
  227. sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
  228. stuffcmd (other, "bf\n");
  229. activator = other;
  230. SUB_UseTargets(); // fire all targets / killtargets
  231. };
  232. /*
  233. QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)
  234. */
  235. void() item_armor1 =
  236. {
  237. self.touch = armor_touch;
  238. self.armortype = 0.3;
  239. self.armorvalue = 100;
  240. precache_model ("progs/armor.mdl");
  241. setmodel (self, "progs/armor.mdl");
  242. self.skin = 0;
  243. setsize (self, '-16 -16 0', '16 16 56');
  244. StartItem ();
  245. };
  246. /*
  247. QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32)
  248. */
  249. void() item_armor2 =
  250. {
  251. self.touch = armor_touch;
  252. self.armortype = 0.6;
  253. self.armorvalue = 150;
  254. precache_model ("progs/armor.mdl");
  255. setmodel (self, "progs/armor.mdl");
  256. self.skin = 1;
  257. setsize (self, '-16 -16 0', '16 16 56');
  258. StartItem ();
  259. };
  260. /*
  261. QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32)
  262. */
  263. void() item_armorInv =
  264. {
  265. self.touch = armor_touch;
  266. self.armortype = 0.8;
  267. self.armorvalue = 200;
  268. precache_model ("progs/armor.mdl");
  269. setmodel (self, "progs/armor.mdl");
  270. self.skin = 2;
  271. setsize (self, '-16 -16 0', '16 16 56');
  272. StartItem ();
  273. };
  274. /*
  275. ===============================================================================
  276. WEAPONS
  277. ===============================================================================
  278. */
  279. void() bound_other_ammo =
  280. {
  281. if (other.ammo_shells > 100)
  282. other.ammo_shells = 100;
  283. if (other.ammo_nails > 200)
  284. other.ammo_nails = 200;
  285. if (other.ammo_rockets > 100)
  286. other.ammo_rockets = 100;
  287. if (other.ammo_cells > 100)
  288. other.ammo_cells = 100;
  289. };
  290. float(float w) RankForWeapon =
  291. {
  292. if (w == IT_LIGHTNING)
  293. return 1;
  294. if (w == IT_ROCKET_LAUNCHER)
  295. return 2;
  296. if (w == IT_SUPER_NAILGUN)
  297. return 3;
  298. if (w == IT_GRENADE_LAUNCHER)
  299. return 4;
  300. if (w == IT_SUPER_SHOTGUN)
  301. return 5;
  302. if (w == IT_NAILGUN)
  303. return 6;
  304. return 7;
  305. };
  306. float (float w) WeaponCode =
  307. {
  308. if (w == IT_SUPER_SHOTGUN)
  309. return 3;
  310. if (w == IT_NAILGUN)
  311. return 4;
  312. if (w == IT_SUPER_NAILGUN)
  313. return 5;
  314. if (w == IT_GRENADE_LAUNCHER)
  315. return 6;
  316. if (w == IT_ROCKET_LAUNCHER)
  317. return 7;
  318. if (w == IT_LIGHTNING)
  319. return 8;
  320. return 1;
  321. };
  322. /*
  323. =============
  324. Deathmatch_Weapon
  325. Deathmatch weapon change rules for picking up a weapon
  326. .float ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
  327. =============
  328. */
  329. void(float old, float new) Deathmatch_Weapon =
  330. {
  331. local float or, nr;
  332. if ( self.flags & FL_ISBOT ) {
  333. return;
  334. } // mal: let bots pick their own weapon.
  335. // change self.weapon if desired
  336. or = RankForWeapon (self.weapon);
  337. nr = RankForWeapon (new);
  338. if ( nr < or )
  339. self.weapon = new;
  340. };
  341. /*
  342. =============
  343. weapon_touch
  344. =============
  345. */
  346. float() W_BestWeapon;
  347. float(entity playerEnt, float old, float new) W_WantsToChangeWeapon;
  348. void() weapon_touch =
  349. {
  350. local float hadammo, best, new, old;
  351. local entity stemp;
  352. local float leave;
  353. new = other.items;
  354. if (!(other.flags & FL_CLIENT))
  355. return;
  356. // if the player was using his best weapon, change up to the new one if better
  357. stemp = self;
  358. self = other;
  359. best = W_BestWeapon();
  360. self = stemp;
  361. if (coop || deathmatch == 2 || deathmatch == 3 || deathmatch == 5)
  362. leave = 1;
  363. else
  364. leave = 0;
  365. if (self.classname == "weapon_nailgun")
  366. {
  367. if (leave && (other.items & IT_NAILGUN) )
  368. return;
  369. hadammo = other.ammo_nails;
  370. new = IT_NAILGUN;
  371. other.ammo_nails = other.ammo_nails + 30;
  372. }
  373. else if (self.classname == "weapon_supernailgun")
  374. {
  375. if (leave && (other.items & IT_SUPER_NAILGUN) )
  376. return;
  377. hadammo = other.ammo_rockets;
  378. new = IT_SUPER_NAILGUN;
  379. other.ammo_nails = other.ammo_nails + 30;
  380. }
  381. else if (self.classname == "weapon_supershotgun")
  382. {
  383. if (leave && (other.items & IT_SUPER_SHOTGUN) )
  384. return;
  385. hadammo = other.ammo_rockets;
  386. new = IT_SUPER_SHOTGUN;
  387. other.ammo_shells = other.ammo_shells + 5;
  388. }
  389. else if (self.classname == "weapon_rocketlauncher")
  390. {
  391. if (leave && (other.items & IT_ROCKET_LAUNCHER) )
  392. return;
  393. hadammo = other.ammo_rockets;
  394. new = IT_ROCKET_LAUNCHER;
  395. other.ammo_rockets = other.ammo_rockets + 5;
  396. }
  397. else if (self.classname == "weapon_grenadelauncher")
  398. {
  399. if (leave && (other.items & IT_GRENADE_LAUNCHER) )
  400. return;
  401. hadammo = other.ammo_rockets;
  402. new = IT_GRENADE_LAUNCHER;
  403. other.ammo_rockets = other.ammo_rockets + 5;
  404. }
  405. else if (self.classname == "weapon_lightning")
  406. {
  407. if (leave && (other.items & IT_LIGHTNING) )
  408. return;
  409. hadammo = other.ammo_rockets;
  410. new = IT_LIGHTNING;
  411. other.ammo_cells = other.ammo_cells + 15;
  412. }
  413. else
  414. objerror ("weapon_touch: unknown classname");
  415. sprint(other, "$qc_got_item", self.netname);
  416. // weapon touch sound
  417. sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
  418. stuffcmd (other, "bf\n");
  419. bound_other_ammo ();
  420. // change to the weapon
  421. old = other.items;
  422. other.items = other.items | new;
  423. stemp = self;
  424. self = other;
  425. if(W_WantsToChangeWeapon(other, old, other.items) == 1)
  426. {
  427. if (!deathmatch)
  428. self.weapon = new;
  429. else
  430. Deathmatch_Weapon (old, new);
  431. }
  432. W_SetCurrentAmmo();
  433. self = stemp;
  434. if (leave)
  435. return;
  436. // remove it in single player, or setup for respawning in deathmatch
  437. self.model = string_null;
  438. self.solid = SOLID_NOT;
  439. if (deathmatch && deathmatch != 2)
  440. self.nextthink = time + 30;
  441. self.think = SUB_regen;
  442. activator = other;
  443. SUB_UseTargets(); // fire all targets / killtargets
  444. };
  445. /*
  446. QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32)
  447. */
  448. void() weapon_supershotgun =
  449. {
  450. precache_model ("progs/g_shot.mdl");
  451. setmodel (self, "progs/g_shot.mdl");
  452. self.weapon = IT_SUPER_SHOTGUN;
  453. self.netname = "$qc_double_shotgun";
  454. self.touch = weapon_touch;
  455. setsize (self, '-16 -16 0', '16 16 56');
  456. StartItem ();
  457. };
  458. /*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  459. */
  460. void() weapon_nailgun =
  461. {
  462. precache_model ("progs/g_nail.mdl");
  463. setmodel (self, "progs/g_nail.mdl");
  464. self.weapon = IT_NAILGUN;
  465. self.netname = "$qc_nailgun";
  466. self.touch = weapon_touch;
  467. setsize (self, '-16 -16 0', '16 16 56');
  468. StartItem ();
  469. };
  470. /*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  471. */
  472. void() weapon_supernailgun =
  473. {
  474. precache_model ("progs/g_nail2.mdl");
  475. setmodel (self, "progs/g_nail2.mdl");
  476. self.weapon = IT_SUPER_NAILGUN;
  477. self.netname = "$qc_super_nailgun";
  478. self.touch = weapon_touch;
  479. setsize (self, '-16 -16 0', '16 16 56');
  480. StartItem ();
  481. };
  482. /*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  483. */
  484. void() weapon_grenadelauncher =
  485. {
  486. precache_model ("progs/g_rock.mdl");
  487. setmodel (self, "progs/g_rock.mdl");
  488. self.weapon = IT_GRENADE_LAUNCHER;
  489. self.netname = "$qc_grenade_launcher";
  490. self.touch = weapon_touch;
  491. setsize (self, '-16 -16 0', '16 16 56');
  492. StartItem ();
  493. };
  494. /*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  495. */
  496. void() weapon_rocketlauncher =
  497. {
  498. precache_model ("progs/g_rock2.mdl");
  499. setmodel (self, "progs/g_rock2.mdl");
  500. self.weapon = IT_ROCKET_LAUNCHER;
  501. self.netname = "$qc_rocket_launcher";
  502. self.touch = weapon_touch;
  503. setsize (self, '-16 -16 0', '16 16 56');
  504. StartItem ();
  505. };
  506. /*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
  507. */
  508. void() weapon_lightning =
  509. {
  510. precache_model ("progs/g_light.mdl");
  511. setmodel (self, "progs/g_light.mdl");
  512. self.weapon = IT_LIGHTNING;
  513. self.netname = "$qc_thunderbolt";
  514. self.touch = weapon_touch;
  515. setsize (self, '-16 -16 0', '16 16 56');
  516. StartItem ();
  517. };
  518. /*
  519. ===============================================================================
  520. AMMO
  521. ===============================================================================
  522. */
  523. void() ammo_touch =
  524. {
  525. local entity stemp;
  526. local float best;
  527. if (other.classname != "player")
  528. return;
  529. if (other.health <= 0)
  530. return;
  531. // if the player was using his best weapon, change up to the new one if better
  532. stemp = self;
  533. self = other;
  534. best = W_BestWeapon();
  535. self = stemp;
  536. // shotgun
  537. if (self.weapon == 1)
  538. {
  539. if (other.ammo_shells >= 100)
  540. return;
  541. other.ammo_shells = other.ammo_shells + self.aflag;
  542. }
  543. // spikes
  544. if (self.weapon == 2)
  545. {
  546. if (other.ammo_nails >= 200)
  547. return;
  548. other.ammo_nails = other.ammo_nails + self.aflag;
  549. }
  550. // rockets
  551. if (self.weapon == 3)
  552. {
  553. if (other.ammo_rockets >= 100)
  554. return;
  555. other.ammo_rockets = other.ammo_rockets + self.aflag;
  556. }
  557. // cells
  558. if (self.weapon == 4)
  559. {
  560. if (other.ammo_cells >= 100)
  561. return;
  562. other.ammo_cells = other.ammo_cells + self.aflag;
  563. }
  564. bound_other_ammo ();
  565. sprint(other, "$qc_got_item", self.netname);
  566. // ammo touch sound
  567. sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  568. stuffcmd (other, "bf\n");
  569. // change to a better weapon if appropriate
  570. if ( other.weapon == best && (W_WantsToChangeWeapon(other, 0, 1) == 1))
  571. {
  572. stemp = self;
  573. self = other;
  574. self.weapon = W_BestWeapon();
  575. W_SetCurrentAmmo ();
  576. self = stemp;
  577. }
  578. // if changed current ammo, update it
  579. stemp = self;
  580. self = other;
  581. W_SetCurrentAmmo();
  582. self = stemp;
  583. // remove it in single player, or setup for respawning in deathmatch
  584. self.model = string_null;
  585. self.solid = SOLID_NOT;
  586. if (deathmatch) {
  587. if (deathmatch == 3 || deathmatch == 5) {
  588. self.nextthink = time + 15;
  589. } else if (deathmatch != 2) {
  590. self.nextthink = time + 30;
  591. }
  592. }
  593. self.think = SUB_regen;
  594. activator = other;
  595. SUB_UseTargets(); // fire all targets / killtargets
  596. };
  597. float WEAPON_BIG2 = 1;
  598. /*
  599. QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big
  600. */
  601. void() item_shells =
  602. {
  603. self.touch = ammo_touch;
  604. if (self.spawnflags & WEAPON_BIG2)
  605. {
  606. precache_model ("maps/b_shell1.bsp");
  607. setmodel (self, "maps/b_shell1.bsp");
  608. self.aflag = 40;
  609. }
  610. else
  611. {
  612. precache_model ("maps/b_shell0.bsp");
  613. setmodel (self, "maps/b_shell0.bsp");
  614. self.aflag = 20;
  615. }
  616. self.weapon = 1;
  617. self.netname = "$qc_shells";
  618. setsize (self, '0 0 0', '32 32 56');
  619. StartItem ();
  620. };
  621. /*
  622. QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big
  623. */
  624. void() item_spikes =
  625. {
  626. self.touch = ammo_touch;
  627. if (self.spawnflags & WEAPON_BIG2)
  628. {
  629. precache_model ("maps/b_nail1.bsp");
  630. setmodel (self, "maps/b_nail1.bsp");
  631. self.aflag = 50;
  632. }
  633. else
  634. {
  635. precache_model ("maps/b_nail0.bsp");
  636. setmodel (self, "maps/b_nail0.bsp");
  637. self.aflag = 25;
  638. }
  639. self.weapon = 2;
  640. self.netname = "$qc_nails";
  641. setsize (self, '0 0 0', '32 32 56');
  642. StartItem ();
  643. };
  644. /*
  645. QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big
  646. */
  647. void() item_rockets =
  648. {
  649. self.touch = ammo_touch;
  650. if (self.spawnflags & WEAPON_BIG2)
  651. {
  652. precache_model ("maps/b_rock1.bsp");
  653. setmodel (self, "maps/b_rock1.bsp");
  654. self.aflag = 10;
  655. }
  656. else
  657. {
  658. precache_model ("maps/b_rock0.bsp");
  659. setmodel (self, "maps/b_rock0.bsp");
  660. self.aflag = 5;
  661. }
  662. self.weapon = 3;
  663. self.netname = "$qc_rockets";
  664. setsize (self, '0 0 0', '32 32 56');
  665. StartItem ();
  666. };
  667. /*
  668. QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big
  669. */
  670. void() item_cells =
  671. {
  672. self.touch = ammo_touch;
  673. if (self.spawnflags & WEAPON_BIG2)
  674. {
  675. precache_model ("maps/b_batt1.bsp");
  676. setmodel (self, "maps/b_batt1.bsp");
  677. self.aflag = 12;
  678. }
  679. else
  680. {
  681. precache_model ("maps/b_batt0.bsp");
  682. setmodel (self, "maps/b_batt0.bsp");
  683. self.aflag = 6;
  684. }
  685. self.weapon = 4;
  686. self.netname = "$qc_cells";
  687. setsize (self, '0 0 0', '32 32 56');
  688. StartItem ();
  689. };
  690. /*
  691. QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big
  692. DO NOT USE THIS!!!! IT WILL BE REMOVED!
  693. */
  694. float WEAPON_SHOTGUN = 1;
  695. float WEAPON_ROCKET = 2;
  696. float WEAPON_SPIKES = 4;
  697. float WEAPON_BIG = 8;
  698. void() item_weapon =
  699. {
  700. self.touch = ammo_touch;
  701. if (self.spawnflags & WEAPON_SHOTGUN)
  702. {
  703. if (self.spawnflags & WEAPON_BIG)
  704. {
  705. precache_model ("maps/b_shell1.bsp");
  706. setmodel (self, "maps/b_shell1.bsp");
  707. self.aflag = 40;
  708. }
  709. else
  710. {
  711. precache_model ("maps/b_shell0.bsp");
  712. setmodel (self, "maps/b_shell0.bsp");
  713. self.aflag = 20;
  714. }
  715. self.weapon = 1;
  716. self.netname = "$qc_shells";
  717. }
  718. if (self.spawnflags & WEAPON_SPIKES)
  719. {
  720. if (self.spawnflags & WEAPON_BIG)
  721. {
  722. precache_model ("maps/b_nail1.bsp");
  723. setmodel (self, "maps/b_nail1.bsp");
  724. self.aflag = 40;
  725. }
  726. else
  727. {
  728. precache_model ("maps/b_nail0.bsp");
  729. setmodel (self, "maps/b_nail0.bsp");
  730. self.aflag = 20;
  731. }
  732. self.weapon = 2;
  733. self.netname = "$qc_spikes";
  734. }
  735. if (self.spawnflags & WEAPON_ROCKET)
  736. {
  737. if (self.spawnflags & WEAPON_BIG)
  738. {
  739. precache_model ("maps/b_rock1.bsp");
  740. setmodel (self, "maps/b_rock1.bsp");
  741. self.aflag = 10;
  742. }
  743. else
  744. {
  745. precache_model ("maps/b_rock0.bsp");
  746. setmodel (self, "maps/b_rock0.bsp");
  747. self.aflag = 5;
  748. }
  749. self.weapon = 3;
  750. self.netname = "$qc_rockets";
  751. }
  752. setsize (self, '0 0 0', '32 32 56');
  753. StartItem ();
  754. };
  755. /*
  756. ===============================================================================
  757. KEYS
  758. ===============================================================================
  759. */
  760. void() key_touch =
  761. {
  762. if (other.classname != "player")
  763. return;
  764. if (other.health <= 0)
  765. return;
  766. if (other.items & self.items)
  767. return;
  768. sprint(other, "$qc_got_item", self.netname);
  769. sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  770. stuffcmd (other, "bf\n");
  771. other.items = other.items | self.items;
  772. if (!coop)
  773. {
  774. self.solid = SOLID_NOT;
  775. self.model = string_null;
  776. }
  777. activator = other;
  778. SUB_UseTargets(); // fire all targets / killtargets
  779. };
  780. void() key_setsounds =
  781. {
  782. if (world.worldtype == WORLDTYPE_MEDIEVAL)
  783. {
  784. precache_sound ("misc/medkey.wav");
  785. self.noise = "misc/medkey.wav";
  786. }
  787. if (world.worldtype == WORLDTYPE_METAL)
  788. {
  789. precache_sound ("misc/runekey.wav");
  790. self.noise = "misc/runekey.wav";
  791. }
  792. if (world.worldtype == WORLDTYPE_BASE)
  793. {
  794. precache_sound2 ("misc/basekey.wav");
  795. self.noise = "misc/basekey.wav";
  796. }
  797. };
  798. /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32)
  799. SILVER key
  800. In order for keys to work
  801. you MUST set your maps
  802. worldtype to one of the
  803. following:
  804. 0: medieval
  805. 1: metal
  806. 2: base
  807. */
  808. void() item_key1 =
  809. {
  810. if (world.worldtype == WORLDTYPE_MEDIEVAL)
  811. {
  812. precache_model ("progs/w_s_key.mdl");
  813. setmodel (self, "progs/w_s_key.mdl");
  814. self.netname = "$qc_silver_key";
  815. }
  816. else if (world.worldtype == WORLDTYPE_METAL)
  817. {
  818. precache_model ("progs/m_s_key.mdl");
  819. setmodel (self, "progs/m_s_key.mdl");
  820. self.netname = "$qc_silver_runekey";
  821. }
  822. else if (world.worldtype == WORLDTYPE_BASE)
  823. {
  824. precache_model2 ("progs/b_s_key.mdl");
  825. setmodel (self, "progs/b_s_key.mdl");
  826. self.netname = "$qc_silver_keycard";
  827. }
  828. key_setsounds();
  829. self.touch = key_touch;
  830. self.items = IT_KEY1;
  831. setsize (self, '-16 -16 -24', '16 16 32');
  832. StartItem ();
  833. };
  834. /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32)
  835. GOLD key
  836. In order for keys to work
  837. you MUST set your maps
  838. worldtype to one of the
  839. following:
  840. 0: medieval
  841. 1: metal
  842. 2: base
  843. */
  844. void() item_key2 =
  845. {
  846. if (world.worldtype == WORLDTYPE_MEDIEVAL)
  847. {
  848. precache_model ("progs/w_g_key.mdl");
  849. setmodel (self, "progs/w_g_key.mdl");
  850. self.netname = "$qc_gold_key";
  851. }
  852. if (world.worldtype == WORLDTYPE_METAL)
  853. {
  854. precache_model ("progs/m_g_key.mdl");
  855. setmodel (self, "progs/m_g_key.mdl");
  856. self.netname = "$qc_gold_runekey";
  857. }
  858. if (world.worldtype == WORLDTYPE_BASE)
  859. {
  860. precache_model2 ("progs/b_g_key.mdl");
  861. setmodel (self, "progs/b_g_key.mdl");
  862. self.netname = "$qc_gold_keycard";
  863. }
  864. key_setsounds();
  865. self.touch = key_touch;
  866. self.items = IT_KEY2;
  867. setsize (self, '-16 -16 -24', '16 16 32');
  868. StartItem ();
  869. };
  870. /*
  871. ===============================================================================
  872. END OF LEVEL RUNES
  873. ===============================================================================
  874. */
  875. void() sigil_touch =
  876. {
  877. if (other.classname != "player")
  878. return;
  879. if (other.health <= 0)
  880. return;
  881. centerprint(other, "$qc_got_rune");
  882. sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  883. stuffcmd (other, "bf\n");
  884. self.solid = SOLID_NOT;
  885. self.model = string_null;
  886. serverflags = serverflags | (self.spawnflags & 15);
  887. self.classname = string_null; // so rune doors won't find it
  888. activator = other;
  889. SUB_UseTargets(); // fire all targets / killtargets
  890. };
  891. /*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
  892. End of level sigil, pick up to end episode and return to jrstart.
  893. */
  894. void() item_sigil =
  895. {
  896. if (!self.spawnflags)
  897. objerror ("no spawnflags");
  898. precache_sound ("misc/runekey.wav");
  899. self.noise = "misc/runekey.wav";
  900. if (self.spawnflags & 1)
  901. {
  902. precache_model ("progs/end1.mdl");
  903. setmodel (self, "progs/end1.mdl");
  904. }
  905. if (self.spawnflags & 2)
  906. {
  907. precache_model2 ("progs/end2.mdl");
  908. setmodel (self, "progs/end2.mdl");
  909. }
  910. if (self.spawnflags & 4)
  911. {
  912. precache_model2 ("progs/end3.mdl");
  913. setmodel (self, "progs/end3.mdl");
  914. }
  915. if (self.spawnflags & 8)
  916. {
  917. precache_model2 ("progs/end4.mdl");
  918. setmodel (self, "progs/end4.mdl");
  919. }
  920. self.touch = sigil_touch;
  921. setsize (self, '-16 -16 -24', '16 16 32');
  922. StartItem ();
  923. };
  924. /*
  925. ===============================================================================
  926. POWERUPS
  927. ===============================================================================
  928. */
  929. void() powerup_touch;
  930. void() powerup_touch =
  931. {
  932. if (other.classname != "player")
  933. return;
  934. if (other.health <= 0)
  935. return;
  936. sprint(other, "$qc_got_item", self.netname);
  937. if (deathmatch)
  938. {
  939. self.mdl = self.model;
  940. if ((self.classname == "item_artifact_invulnerability") || (self.classname == "item_artifact_invisibility"))
  941. self.nextthink = time + 60*5;
  942. else
  943. self.nextthink = time + 60;
  944. self.think = SUB_regen;
  945. }
  946. sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
  947. stuffcmd (other, "bf\n");
  948. self.solid = SOLID_NOT;
  949. other.items = other.items | self.items;
  950. self.model = string_null;
  951. // do the apropriate action
  952. if (self.classname == "item_artifact_envirosuit")
  953. {
  954. other.rad_time = 1;
  955. other.radsuit_finished = time + 30;
  956. }
  957. if (self.classname == "item_artifact_invulnerability")
  958. {
  959. other.invincible_time = 1;
  960. other.invincible_finished = time + 30;
  961. }
  962. if (self.classname == "item_artifact_invisibility")
  963. {
  964. other.invisible_time = 1;
  965. other.invisible_finished = time + 30;
  966. }
  967. if (self.classname == "item_artifact_super_damage")
  968. {
  969. other.super_time = 1;
  970. other.super_damage_finished = time + 30;
  971. }
  972. activator = other;
  973. SUB_UseTargets(); // fire all targets / killtargets
  974. };
  975. /*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32)
  976. Player is invulnerable for 30 seconds
  977. */
  978. void() item_artifact_invulnerability =
  979. {
  980. self.touch = powerup_touch;
  981. precache_model ("progs/invulner.mdl");
  982. precache_sound ("items/protect.wav");
  983. precache_sound ("items/protect2.wav");
  984. precache_sound ("items/protect3.wav");
  985. self.noise = "items/protect.wav";
  986. setmodel (self, "progs/invulner.mdl");
  987. self.netname = "$qc_pentagram_of_protection";
  988. self.items = IT_INVULNERABILITY;
  989. setsize (self, '-16 -16 -24', '16 16 32');
  990. StartItem ();
  991. };
  992. /*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32)
  993. Player takes no damage from water or slime for 30 seconds
  994. */
  995. void() item_artifact_envirosuit =
  996. {
  997. self.touch = powerup_touch;
  998. precache_model ("progs/suit.mdl");
  999. precache_sound ("items/suit.wav");
  1000. precache_sound ("items/suit2.wav");
  1001. self.noise = "items/suit.wav";
  1002. setmodel (self, "progs/suit.mdl");
  1003. self.netname = "$qc_biosuit";
  1004. self.items = IT_SUIT;
  1005. setsize (self, '-16 -16 -24', '16 16 32');
  1006. StartItem ();
  1007. };
  1008. /*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32)
  1009. Player is invisible for 30 seconds
  1010. */
  1011. void() item_artifact_invisibility =
  1012. {
  1013. self.touch = powerup_touch;
  1014. precache_model ("progs/invisibl.mdl");
  1015. precache_sound ("items/inv1.wav");
  1016. precache_sound ("items/inv2.wav");
  1017. precache_sound ("items/inv3.wav");
  1018. self.noise = "items/inv1.wav";
  1019. setmodel (self, "progs/invisibl.mdl");
  1020. self.netname = "$qc_ring_of_shadows";
  1021. self.items = IT_INVISIBILITY;
  1022. setsize (self, '-16 -16 -24', '16 16 32');
  1023. StartItem ();
  1024. };
  1025. /*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32)
  1026. The next attack from the player will do 4x damage
  1027. */
  1028. void() item_artifact_super_damage =
  1029. {
  1030. self.touch = powerup_touch;
  1031. precache_model ("progs/quaddama.mdl");
  1032. precache_sound ("items/damage.wav");
  1033. precache_sound ("items/damage2.wav");
  1034. precache_sound ("items/damage3.wav");
  1035. self.noise = "items/damage.wav";
  1036. setmodel (self, "progs/quaddama.mdl");
  1037. self.netname = "$qc_quad_damage";
  1038. self.items = IT_QUAD;
  1039. setsize (self, '-16 -16 -24', '16 16 32');
  1040. StartItem ();
  1041. };
  1042. /*
  1043. ===============================================================================
  1044. PLAYER BACKPACKS
  1045. ===============================================================================
  1046. */
  1047. void() BackpackTouch =
  1048. {
  1049. local float best, old, new;
  1050. local entity stemp;
  1051. local float acount;
  1052. if (other.classname != "player")
  1053. return;
  1054. if (other.health <= 0)
  1055. return;
  1056. acount = 0;
  1057. sprint(other, "$qc_backpack_got");
  1058. if (self.items)
  1059. {
  1060. if ((other.items & self.items) == 0)
  1061. {
  1062. acount = 1;
  1063. sprint(other, "{}", self.netname);
  1064. }
  1065. }
  1066. // if the player was using his best weapon, change up to the new one if better
  1067. stemp = self;
  1068. self = other;
  1069. best = W_BestWeapon();
  1070. self = stemp;
  1071. // change weapons
  1072. other.ammo_shells = other.ammo_shells + self.ammo_shells;
  1073. other.ammo_nails = other.ammo_nails + self.ammo_nails;
  1074. other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
  1075. other.ammo_cells = other.ammo_cells + self.ammo_cells;
  1076. new = self.items;
  1077. if (!new)
  1078. new = other.weapon;
  1079. old = other.items;
  1080. other.items = other.items | self.items;
  1081. bound_other_ammo ();
  1082. if (self.ammo_shells)
  1083. {
  1084. if (acount)
  1085. sprint(other, ", ");
  1086. acount = 1;
  1087. sprint(other, "$qc_backpack_shells", ftos(self.ammo_shells));
  1088. }
  1089. if (self.ammo_nails)
  1090. {
  1091. if (acount)
  1092. sprint(other, ", ");
  1093. acount = 1;
  1094. sprint(other, "$qc_backpack_nails", ftos(self.ammo_nails));
  1095. }
  1096. if (self.ammo_rockets)
  1097. {
  1098. if (acount)
  1099. sprint(other, ", ");
  1100. acount = 1;
  1101. sprint(other, "$qc_backpack_rockets", ftos(self.ammo_rockets));
  1102. }
  1103. if (self.ammo_cells)
  1104. {
  1105. if (acount)
  1106. sprint(other, ", ");
  1107. acount = 1;
  1108. sprint(other, "$qc_backpack_cells", ftos(self.ammo_cells));
  1109. }
  1110. sprint (other, "\n");
  1111. // backpack touch sound
  1112. sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  1113. stuffcmd (other, "bf\n");
  1114. remove(self);
  1115. self = other;
  1116. // change to the weapon
  1117. if(W_WantsToChangeWeapon(other, old, other.items) == 1)
  1118. {
  1119. if (self.flags & FL_INWATER)
  1120. {
  1121. if (new != IT_LIGHTNING)
  1122. {
  1123. Deathmatch_Weapon (old, new);
  1124. }
  1125. }
  1126. else
  1127. {
  1128. Deathmatch_Weapon (old, new);
  1129. }
  1130. }
  1131. W_SetCurrentAmmo ();
  1132. };
  1133. /*
  1134. ===============
  1135. DropBackpack
  1136. ===============
  1137. */
  1138. void() DropBackpack =
  1139. {
  1140. local entity item;
  1141. if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
  1142. return; // nothing in it
  1143. item = spawn();
  1144. item.origin = self.origin - '0 0 24';
  1145. item.items = self.weapon;
  1146. item.classname = "item_backpack"; // added for bots.
  1147. if (item.items == IT_AXE)
  1148. item.netname = "$qc_axe";
  1149. else if (item.items == IT_SHOTGUN)
  1150. item.netname = "$qc_shotgun";
  1151. else if (item.items == IT_SUPER_SHOTGUN)
  1152. item.netname = "$qc_double_shotgun";
  1153. else if (item.items == IT_NAILGUN)
  1154. item.netname = "$qc_nailgun";
  1155. else if (item.items == IT_SUPER_NAILGUN)
  1156. item.netname = "$qc_super_nailgun";
  1157. else if (item.items == IT_GRENADE_LAUNCHER)
  1158. item.netname = "$qc_grenade_launcher";
  1159. else if (item.items == IT_ROCKET_LAUNCHER)
  1160. item.netname = "$qc_rocket_launcher";
  1161. else if (item.items == IT_LIGHTNING)
  1162. item.netname = "$qc_thunderbolt";
  1163. item.ammo_shells = self.ammo_shells;
  1164. item.ammo_nails = self.ammo_nails;
  1165. item.ammo_rockets = self.ammo_rockets;
  1166. item.ammo_cells = self.ammo_cells;
  1167. // include some ammo in the backpack if the weapon is being given
  1168. if (item.ammo_shells < 5 && (item.items == IT_SHOTGUN || item.items == IT_SUPER_SHOTGUN)) {
  1169. item.ammo_shells = 5;
  1170. }
  1171. if (item.ammo_nails < 20 && (item.items == IT_NAILGUN || item.items == IT_SUPER_NAILGUN)) {
  1172. item.ammo_nails = 20;
  1173. }
  1174. if (item.ammo_rockets < 5 && (item.items == IT_GRENADE_LAUNCHER || item.items == IT_ROCKET_LAUNCHER)) {
  1175. item.ammo_rockets = 5;
  1176. }
  1177. if (item.ammo_cells < 15 && item.items == IT_LIGHTNING) {
  1178. item.ammo_cells = 15;
  1179. }
  1180. item.velocity_z = 300;
  1181. item.velocity_x = -100 + (random() * 200);
  1182. item.velocity_y = -100 + (random() * 200);
  1183. item.flags = FL_ITEM;
  1184. item.solid = SOLID_TRIGGER;
  1185. item.movetype = MOVETYPE_TOSS;
  1186. setmodel (item, "progs/backpack.mdl");
  1187. setsize (item, '-16 -16 0', '16 16 56');
  1188. item.touch = BackpackTouch;
  1189. item.nextthink = time + 120; // remove after 2 minutes
  1190. item.think = SUB_Remove;
  1191. };