Advertisement
Guest User

Rotation QuakeC 2

a guest
Oct 26th, 2011
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.20 KB | None | 0 0
  1.  
  2. float DOOR_START_OPEN = 1;
  3. float DOOR_DONT_LINK = 4;
  4. float DOOR_GOLD_KEY = 8;
  5. float DOOR_SILVER_KEY = 16;
  6. float DOOR_TOGGLE = 32;
  7. float DOOR_BRONZE_KEY = 64;
  8. float DOOR_PLATINUM_KEY = 128;
  9.  
  10. /*
  11.  
  12. Doors are similar to buttons, but can spawn a fat trigger field around them
  13. to open without a touch, and they link together to form simultanious
  14. double/quad doors.
  15.  
  16. Door.owner is the master door. If there is only one door, it points to itself.
  17. If multiple doors, all will point to a single one.
  18.  
  19. Door.enemy chains from the master door through all doors linked in the chain.
  20.  
  21. */
  22.  
  23. /*
  24. =============================================================================
  25.  
  26. THINK FUNCTIONS
  27.  
  28. =============================================================================
  29. */
  30.  
  31. void() door_go_down;
  32. void() door_go_up;
  33.  
  34. void() door_blocked =
  35. {
  36. // other.deathtype = "squish"; // QIP, Supa
  37. T_Damage (other, self, self.goalentity, self.dmg, DTH_WORLD_SQUISH, FALSE, 1); // QIP, Supa
  38.  
  39. if (!self.model)
  40. return;
  41.  
  42. // if a door has a negative wait, it would never come back if blocked,
  43. // so let it just squash the object to death real fast
  44. if (self.wait >= 0)
  45. {
  46. if (self.state == STATE_DOWN)
  47. door_go_up ();
  48. else
  49. door_go_down ();
  50. }
  51. };
  52.  
  53. void() door_hit_top =
  54. {
  55. // dprint ("dhittop\n");
  56.  
  57. if (self.continue_movesound)
  58. sound (self, CHAN_AUTO, self.noise1, 1, ATTN_NORM); // gb, was CHAN_VOICE
  59. else
  60. sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
  61.  
  62. self.state = STATE_TOP;
  63.  
  64. if (self.spawnflags & DOOR_TOGGLE)
  65. {
  66. // ROTATE
  67. if (self.classname == "door_rotating") {
  68. self.touch = SUB_Null;
  69. self.th_die = SUB_Null;
  70. }
  71. // R
  72. return; // don't come down automatically
  73. }
  74. self.think = door_go_down;
  75. self.nextthink = self.ltime + self.wait;
  76. // ROTATE
  77. if (self.classname == "door_rotating") {
  78. if (self.health)
  79. {
  80. self.takedamage = 1;
  81. self.th_die = door_killed;
  82. }
  83. }
  84. // R
  85. };
  86.  
  87. void() door_hit_bottom =
  88. {
  89. // dprint ("dhitbottom\n");
  90.  
  91. if (self.continue_movesound)
  92. sound (self, CHAN_AUTO, self.noise1, 1, ATTN_NORM); // gb, plays the stop sound *and* the move sound
  93. else
  94. sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM); // gb, cuts the movesound
  95.  
  96. self.state = STATE_BOTTOM;
  97.  
  98. // ROTATE
  99. if (self.classname == "door_rotating") {
  100. if(!(self.spawnflags & DOOR_TOGGLE))
  101. {
  102. self.touch = door_touch;
  103. self.solid = SOLID_BSP;
  104. }
  105. if (self.health)
  106. {
  107. self.takedamage = 1;
  108. self.th_die = door_killed;
  109. }
  110. }
  111. // R
  112. };
  113.  
  114. void() door_go_down =
  115. {
  116. // dprint ("doorgodown\n");
  117.  
  118. sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
  119. if (self.max_health)
  120. {
  121. self.takedamage = DAMAGE_YES;
  122. self.health = self.max_health;
  123. }
  124.  
  125. self.state = STATE_DOWN;
  126.  
  127. // ROTATE
  128. if (self.classname == "door_rotating") {
  129. SUB_CalcAngleMove (self.pos1, self.speed, door_hit_bottom);
  130. // SUB_UseTargets();
  131. self.takedamage = 0;
  132. }
  133. else
  134. // R
  135. SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
  136. };
  137.  
  138. void() door_go_up =
  139. {
  140. // dprint ("doorgoup\n");
  141.  
  142. if (self.state == STATE_UP)
  143. return; // allready going up
  144.  
  145. if (self.state == STATE_TOP)
  146. { // reset top wait time
  147. self.nextthink = self.ltime + self.wait;
  148. return;
  149. }
  150.  
  151. sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
  152. self.state = STATE_UP;
  153.  
  154. // ROTATE
  155. if (self.classname == "door_rotating") {
  156. SUB_CalcAngleMove (self.pos2, self.speed, door_hit_top);
  157. self.takedamage = 0;
  158. }
  159. else
  160. // R
  161. SUB_CalcMove (self.pos2, self.speed, door_hit_top);
  162.  
  163. SUB_UseTargets();
  164. };
  165.  
  166.  
  167. /*
  168. =============================================================================
  169.  
  170. ACTIVATION FUNCTIONS
  171.  
  172. =============================================================================
  173. */
  174.  
  175. void() door_fire =
  176. {
  177. local entity oself;
  178. local entity starte, te, finder_ent; // ROTATE
  179.  
  180. if (self.owner != self)
  181. objerror ("door_fire: self.owner != self");
  182.  
  183. // play use key sound
  184.  
  185. if ((self.items) || (self.items2))
  186. sound (self, CHAN_ITEM, self.noise4, 1, ATTN_NORM);
  187.  
  188. self.message = string_null; // no more message
  189. oself = self;
  190.  
  191. if (self.spawnflags & DOOR_TOGGLE)
  192. {
  193. if (self.state == STATE_UP || self.state == STATE_TOP)
  194. {
  195. starte = self;
  196. do
  197. {
  198. door_go_down ();
  199. self = self.enemy;
  200. } while ( (self != starte) && (self != world) );
  201. self = oself;
  202. return;
  203. }
  204. }
  205.  
  206. // trigger all paired doors
  207. // ROTATE
  208. if (self.classname == "door_rotating" && (self.linkname))
  209. {
  210. // linking rotating doors is fubar'd... hence we do it manually, and this time it even works
  211. finder_ent = find (world,linkname,self.linkname);
  212.  
  213. while (finder_ent)
  214. {
  215. if (/* finder_ent != self && */finder_ent.linkname != string_null && finder_ent.linkname == self.linkname/* && finder_ent.touch != SUB_Null*/ )
  216. {
  217. te = self;
  218. self = finder_ent;
  219. door_go_up();
  220. self = te;
  221. }
  222. finder_ent = find (finder_ent, linkname, self.linkname);
  223. }
  224. }
  225. // R
  226. else
  227. {
  228. starte = self;
  229. do
  230. {
  231. self.goalentity = activator; // QIP
  232. door_go_up ();
  233. self = self.enemy;
  234. } while ( (self != starte) && (self != world) );
  235. self = oself;
  236. }
  237. };
  238.  
  239.  
  240. void() door_use =
  241. {
  242. local entity oself;
  243.  
  244. self.message = ""; // door message are for touch only
  245. self.owner.message = "";
  246. self.enemy.message = "";
  247. oself = self;
  248. self = self.owner;
  249. door_fire ();
  250. self = oself;
  251. };
  252.  
  253.  
  254. void() door_trigger_touch =
  255. {
  256. if (other.health <= 0)
  257. return;
  258.  
  259. if (time < self.attack_finished)
  260. return;
  261. self.attack_finished = time + 1;
  262.  
  263. activator = other;
  264.  
  265. self = self.owner;
  266. door_use ();
  267. };
  268.  
  269.  
  270. void() door_killed =
  271. {
  272. local entity oself;
  273.  
  274. oself = self;
  275. self = self.owner;
  276. self.health = self.max_health;
  277. self.takedamage = DAMAGE_NO; // wil be reset upon return
  278. door_use ();
  279. self = oself;
  280. };
  281.  
  282.  
  283. float (entity e1, entity e2) EntitiesTouching;
  284. /*
  285. ================
  286. door_touch
  287.  
  288. Prints messages and opens key doors
  289. ================
  290. */
  291. // 20101029 Supa func_door with multiple keys now requires the player to have all keys to open it
  292. void() door_touch =
  293. {
  294. local string firstkey,
  295. secondkey,
  296. thirdkey,
  297. fourthkey,
  298. keystr;
  299. local float numkeys,
  300. keysneeded;
  301.  
  302. // ROTATE
  303. local entity finder_ent, te;
  304. // R
  305. if (other.classname != "player")
  306. return;
  307. if (self.owner.attack_finished > time)
  308. return;
  309.  
  310. if (other.classname == "player" && (self.health > 0) ) // gb, any door with health set must be shot open
  311. return;
  312.  
  313. self.owner.attack_finished = time + 2;
  314.  
  315. if (self.owner.message != "")
  316. {
  317. centerprint (other, self.owner.message);
  318. sound (other, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
  319. }
  320.  
  321. // key door stuff
  322. if ((!self.items) && (!self.items2) && (!self.classname == "door_rotating")) // gb, the latter must touch
  323. return;
  324.  
  325. // FIXME: blink key on player's status bar
  326. if (((self.items & other.items ) != self.items ) ||
  327. ((self.items2 & other.items2 ) != self.items2) )
  328. {
  329. // going to have to do this the tedious way until we have strcat -_-
  330.  
  331. sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
  332.  
  333. // do one pass first to check how many keys are needed and consquently how many commas we'll need
  334.  
  335. if ((self.owner.items & IT_KEY1) &&
  336. (!(other.items & IT_KEY1)) ) {numkeys++; keysneeded = keysneeded | IT_KEY1; }
  337.  
  338. if ((self.owner.items & IT_KEY2) &&
  339. (!(other.items & IT_KEY2)) ) {numkeys++; keysneeded = keysneeded | IT_KEY2; }
  340.  
  341. if ((self.owner.items2 & IT_KEY3) &&
  342. (!(other.items2 & IT_KEY3)) ) {numkeys++; keysneeded = keysneeded | IT_KEY3; }
  343.  
  344. if ((self.owner.items2 & IT_KEY4) &&
  345. (!(other.items2 & IT_KEY4)) ) {numkeys++; keysneeded = keysneeded | IT_KEY4; }
  346.  
  347. // find what key type name we'll need
  348. if (world.worldtype == 2) {if (numkeys > 1) keystr = " keycards\n"; else keystr = " keycard\n"; }
  349. else if (world.worldtype == 1) {if (numkeys > 1) keystr = " runekeys\n"; else keystr = " runekey\n"; }
  350. else if (world.worldtype == 0) {if (numkeys > 1) keystr = " keys\n"; else keystr = " key\n"; }
  351.  
  352. // now do a second pass and build the the key colour list
  353.  
  354. if ((self.owner.items & IT_KEY1) &&
  355. (!(other.items & IT_KEY1)) ) // need silver
  356. firstkey = "silver";
  357.  
  358. if ((self.owner.items & IT_KEY2) &&
  359. (!(other.items & IT_KEY2)) ) // need gold
  360. {
  361. if (firstkey) // ~/COMMA COMMA COMMA COMMA COMMA COMMA COMMA CHAMELEON/~
  362. {
  363. if (keysneeded & IT_KEY3 ||
  364. keysneeded & IT_KEY4 )
  365. secondkey = ", gold";
  366. else secondkey = " and gold";
  367. }
  368. else secondkey = "gold";
  369. }
  370.  
  371. if ((self.owner.items2 & IT_KEY3) &&
  372. (!(other.items2 & IT_KEY3)) ) // need bronze
  373. {
  374. if (firstkey ||
  375. secondkey ) // ~/YOU COMMA AND GO~/~
  376. {
  377. if (keysneeded & IT_KEY4)
  378. thirdkey = ", bronze";
  379. else thirdkey = " and bronze";
  380. }
  381. else thirdkey = "bronze";
  382. }
  383.  
  384. if ((self.owner.items2 & IT_KEY4) &&
  385. (!(other.items2 & IT_KEY4)) ) // need platinum
  386. {
  387. if (firstkey ||
  388. secondkey ||
  389. thirdkey ) // ~/YOU COMMA AND GOOOO~/~
  390. {
  391. fourthkey = " and platinum";
  392. }
  393. else fourthkey = "platinum";
  394. }
  395.  
  396.  
  397. frik_big_centerprint (other, "You need the ", firstkey, secondkey, thirdkey, fourthkey, keystr, "");
  398.  
  399. return;
  400. }
  401.  
  402. other.items = other.items - self.items;
  403. other.items2 = other.items2 - self.items2;
  404.  
  405. self.touch = SUB_Null;
  406.  
  407. if (self.enemy)
  408. self.enemy.touch = SUB_Null; // get paired door
  409.  
  410. door_use ();
  411.  
  412. // ROTATE
  413. if (self.classname == "door_rotating") {
  414. // linking rotating doors is fubar'd... hence we do it manually, and this time it even works
  415. finder_ent = find (world,linkname,self.linkname);
  416.  
  417. while (finder_ent)
  418. {
  419. if ( finder_ent != self && finder_ent.linkname != string_null && finder_ent.linkname == self.linkname && finder_ent.touch != SUB_Null )
  420. {
  421. te = self;
  422. self = finder_ent;
  423. self.touch();
  424. self = te;
  425. }
  426. finder_ent = find (finder_ent, linkname, self.linkname);
  427. }
  428. }
  429. // R
  430.  
  431. };
  432.  
  433. /*
  434. =============================================================================
  435.  
  436. SPAWNING FUNCTIONS
  437.  
  438. =============================================================================
  439. */
  440.  
  441.  
  442. entity(vector fmins, vector fmaxs) spawn_field =
  443. {
  444. local entity trigger;
  445. local vector t1, t2;
  446.  
  447. trigger = spawn();
  448. trigger.movetype = MOVETYPE_NONE;
  449. trigger.solid = SOLID_TRIGGER;
  450. trigger.owner = self;
  451. trigger.touch = door_trigger_touch;
  452.  
  453. t1 = fmins;
  454. t2 = fmaxs;
  455. setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
  456. return (trigger);
  457. };
  458.  
  459.  
  460. float (entity e1, entity e2) EntitiesTouching =
  461. {
  462. if (e1.mins_x > e2.maxs_x)
  463. return FALSE;
  464. if (e1.mins_y > e2.maxs_y)
  465. return FALSE;
  466. if (e1.mins_z > e2.maxs_z)
  467. return FALSE;
  468. if (e1.maxs_x < e2.mins_x)
  469. return FALSE;
  470. if (e1.maxs_y < e2.mins_y)
  471. return FALSE;
  472. if (e1.maxs_z < e2.mins_z)
  473. return FALSE;
  474. return TRUE;
  475. };
  476.  
  477.  
  478. /*
  479. =============
  480. LinkDoors
  481. =============
  482. */
  483. void() LinkDoors =
  484. {
  485. local entity t, starte;
  486. local vector cmins, cmaxs;
  487.  
  488. if (self.enemy)
  489. return; // already linked by another door
  490. if (self.spawnflags & 4)
  491. {
  492. self.owner = self.enemy = self;
  493. return; // don't want to link this door
  494. }
  495.  
  496. //cmins = self.mins;
  497. //cmaxs = self.maxs;
  498.  
  499. //ijed Thanks Preach - fix for trigger field
  500. cmins = self.mins + self.origin;
  501. cmaxs = self.maxs + self.origin;
  502.  
  503. starte = self;
  504. t = self;
  505.  
  506. do
  507. {
  508. self.owner = starte; // master door
  509.  
  510. if (self.health)
  511. starte.health = self.health;
  512. if (self.targetname)
  513. starte.targetname = self.targetname;
  514. if (self.message != "")
  515. starte.message = self.message;
  516.  
  517. t = find (t, classname, self.classname);
  518. if (!t)
  519. {
  520. self.enemy = starte; // make the chain a loop
  521.  
  522. // shootable, fired, or key doors just needed the owner/enemy links,
  523. // they don't spawn a field
  524.  
  525. self = self.owner;
  526.  
  527. if (self.health)
  528. return;
  529. if (self.targetname)
  530. return;
  531. if (self.items)
  532. return;
  533. if (self.items2)
  534. return;
  535.  
  536. self.owner.trigger_field = spawn_field(cmins, cmaxs);
  537.  
  538. return;
  539. }
  540.  
  541. if (EntitiesTouching(self,t))
  542. {
  543. if (t.enemy)
  544. objerror ("cross connected doors");
  545.  
  546. self.enemy = t;
  547. self = t;
  548.  
  549. if (t.mins_x < cmins_x)
  550. cmins_x = t.mins_x;
  551. if (t.mins_y < cmins_y)
  552. cmins_y = t.mins_y;
  553. if (t.mins_z < cmins_z)
  554. cmins_z = t.mins_z;
  555. if (t.maxs_x > cmaxs_x)
  556. cmaxs_x = t.maxs_x;
  557. if (t.maxs_y > cmaxs_y)
  558. cmaxs_y = t.maxs_y;
  559. if (t.maxs_z > cmaxs_z)
  560. cmaxs_z = t.maxs_z;
  561. }
  562. } while (1 );
  563.  
  564. };
  565.  
  566.  
  567. /*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE BRONZE_KEY PLATINUM_KEY
  568. if two doors touch, they are assumed to be connected and operate as a unit.
  569.  
  570. TOGGLE causes the door to wait in both the start and end states for a trigger event.
  571.  
  572. START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not usefull for touch or takedamage doors).
  573.  
  574. Key doors are allways wait -1.
  575.  
  576. "message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
  577. "angle" determines the opening direction
  578. "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
  579. "health" if set, door must be shot open
  580. "speed" movement speed (100 default)
  581. "wait" wait before returning (3 default, -1 = never return)
  582. "lip" lip remaining at end of move (8 default)
  583. "dmg" damage to inflict when blocked (2 default)
  584. "noise1" overrides the stopping sound if sounds 0
  585. "noise2" overrides the moving sound if sounds 0
  586. "continue_movesound" allows the move sound to continue, usually it is cut out as soon as the stop sound plays
  587. "sounds"
  588. 0) no sound / sounds set manually
  589. 1) stone
  590. 2) base
  591. 3) stone chain
  592. 4) screechy metal
  593. */
  594.  
  595. void() func_door =
  596.  
  597. {
  598. if (world.worldtype == 0)
  599. {
  600. precache_sound ("doors/medtry.wav");
  601. precache_sound ("doors/meduse.wav");
  602. self.noise3 = "doors/medtry.wav";
  603. self.noise4 = "doors/meduse.wav";
  604. }
  605. else if (world.worldtype == 1)
  606. {
  607. precache_sound ("doors/runetry.wav");
  608. precache_sound ("doors/runeuse.wav");
  609. self.noise3 = "doors/runetry.wav";
  610. self.noise4 = "doors/runeuse.wav";
  611. }
  612. else if (world.worldtype == 2)
  613. {
  614. precache_sound ("doors/basetry.wav");
  615. precache_sound ("doors/baseuse.wav");
  616. self.noise3 = "doors/basetry.wav";
  617. self.noise4 = "doors/baseuse.wav";
  618. }
  619. else
  620. {
  621. dprint ("no worldtype set!\n");
  622. }
  623.  
  624. if (self.sounds == 0)
  625. {
  626. if (!self.noise1) // gb
  627. self.noise1 = "misc/null.wav";
  628.  
  629. if (!self.noise2) // gb
  630. self.noise2 = "misc/null.wav";
  631.  
  632. precache_sound (self.noise1);
  633. precache_sound (self.noise2);
  634. }
  635. if (self.sounds == 1)
  636. {
  637. precache_sound ("doors/drclos4.wav");
  638. precache_sound ("doors/doormv1.wav");
  639. self.noise1 = "doors/drclos4.wav";
  640. self.noise2 = "doors/doormv1.wav";
  641. }
  642. if (self.sounds == 2)
  643. {
  644. precache_sound ("doors/hydro1.wav");
  645. precache_sound ("doors/hydro2.wav");
  646. self.noise2 = "doors/hydro1.wav";
  647. self.noise1 = "doors/hydro2.wav";
  648. }
  649. if (self.sounds == 3)
  650. {
  651. precache_sound ("doors/stndr1.wav");
  652. precache_sound ("doors/stndr2.wav");
  653. self.noise2 = "doors/stndr1.wav";
  654. self.noise1 = "doors/stndr2.wav";
  655. }
  656. if (self.sounds == 4)
  657. {
  658. precache_sound ("doors/ddoor1.wav");
  659. precache_sound ("doors/ddoor2.wav");
  660. self.noise1 = "doors/ddoor2.wav";
  661. self.noise2 = "doors/ddoor1.wav";
  662. }
  663.  
  664.  
  665. SetMovedir ();
  666.  
  667. self.max_health = self.health;
  668. self.solid = SOLID_BSP;
  669. self.movetype = MOVETYPE_PUSH;
  670. setorigin (self, self.origin);
  671. setmodel (self, self.model);
  672. self.classname = "door";
  673.  
  674. self.blocked = door_blocked;
  675. self.use = door_use;
  676.  
  677. // Supa changed to add bits to allow multiple keys
  678. if (self.spawnflags & DOOR_SILVER_KEY)
  679. self.items = self.items | IT_KEY1;
  680. if (self.spawnflags & DOOR_GOLD_KEY)
  681. self.items = self.items | IT_KEY2;
  682. if (self.spawnflags & DOOR_BRONZE_KEY)
  683. self.items2 = self.items2 | IT_KEY3; //items2 -otp
  684. if (self.spawnflags & DOOR_PLATINUM_KEY)
  685. self.items2 = self.items2 | IT_KEY4; //items2 -otp
  686.  
  687. if (!self.speed)
  688. self.speed = 100;
  689. if (!self.wait)
  690. self.wait = 3;
  691. if (!self.lip)
  692. self.lip = 8;
  693. if (!self.dmg)
  694. self.dmg = 2;
  695.  
  696. self.pos1 = self.origin;
  697. self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
  698.  
  699. // DOOR_START_OPEN is to allow an entity to be lighted in the closed position
  700. // but spawn in the open position
  701. if (self.spawnflags & DOOR_START_OPEN)
  702. {
  703. setorigin (self, self.pos2);
  704. self.pos2 = self.pos1;
  705. self.pos1 = self.origin;
  706. }
  707.  
  708. self.state = STATE_BOTTOM;
  709.  
  710. if (self.health)
  711. {
  712. self.takedamage = DAMAGE_YES;
  713. self.th_die = door_killed;
  714. self.nobleed = TRUE;// pOx - No bleed patch
  715. }
  716.  
  717. if ((self.items) || (self.items2))
  718. self.wait = -1;
  719.  
  720. self.touch = door_touch;
  721.  
  722. // LinkDoors can't be done until all of the doors have been spawned, so
  723. // the sizes can be detected properly.
  724. self.think = LinkDoors;
  725. self.nextthink = self.ltime + 0.1;
  726. };
  727.  
  728. void() func_door_model = //ijed A model instead of being a brush entity
  729. {
  730. if ((self.mdl) || (self.model))
  731. {
  732. if (self.mdl)
  733. {
  734. precache_model (self.mdl);
  735. self.model = self.mdl;
  736. }
  737. precache_model (self.model);
  738. setmodel (self, self.model);
  739. }
  740. else
  741. {
  742. dprint ("null func_door_model at: ");
  743. dprint (vtos (self.origin));
  744. dprint ("\n");
  745. }
  746.  
  747. func_door();
  748. };
  749.  
  750. /*
  751. =============================================================================
  752.  
  753. SECRET DOORS
  754.  
  755. =============================================================================
  756. */
  757.  
  758. void() fd_secret_move1;
  759. void() fd_secret_move2;
  760. void() fd_secret_move3;
  761. void() fd_secret_move4;
  762. void() fd_secret_move5;
  763. void() fd_secret_move6;
  764. void() fd_secret_done;
  765.  
  766. float SECRET_OPEN_ONCE = 1; // stays open
  767. float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
  768. float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
  769. float SECRET_NO_SHOOT = 8; // only opened by trigger
  770. float SECRET_YES_SHOOT = 16; // shootable even if targeted
  771.  
  772.  
  773. void () fd_secret_use =
  774. {
  775. local float temp;
  776.  
  777. self.health = 10000;
  778.  
  779. // exit if still moving around...
  780. if (self.origin != self.oldorigin)
  781. return;
  782.  
  783. self.message = string_null; // no more message
  784.  
  785. SUB_UseTargets(); // fire all targets / killtargets
  786.  
  787. if (!(self.spawnflags & SECRET_NO_SHOOT))
  788. {
  789. self.th_pain = SUB_Null;
  790. self.takedamage = DAMAGE_NO;
  791. }
  792. self.velocity = '0 0 0';
  793.  
  794. // Make a sound, wait a little...
  795.  
  796. sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
  797. self.nextthink = self.ltime + 0.1;
  798.  
  799. temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
  800. makevectors(self.mangle);
  801.  
  802. if (!self.t_width)
  803. {
  804. if (self.spawnflags & SECRET_1ST_DOWN)
  805. self. t_width = fabs(v_up * self.size);
  806. else
  807. self. t_width = fabs(v_right * self.size);
  808. }
  809.  
  810. if (!self.t_length)
  811. self. t_length = fabs(v_forward * self.size);
  812.  
  813. if (self.spawnflags & SECRET_1ST_DOWN)
  814. self.dest1 = self.origin - v_up * self.t_width;
  815. else
  816. self.dest1 = self.origin + v_right * (self.t_width * temp);
  817.  
  818. self.dest2 = self.dest1 + v_forward * self.t_length;
  819. SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);
  820. sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
  821. };
  822.  
  823. // Wait after first movement...
  824. void () fd_secret_move1 =
  825. {
  826. self.nextthink = self.ltime + 1.0;
  827. self.think = fd_secret_move2;
  828. sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
  829. };
  830.  
  831. // Start moving sideways w/sound...
  832. void () fd_secret_move2 =
  833. {
  834. sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
  835. SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);
  836. };
  837.  
  838. // Wait here until time to go back...
  839. void () fd_secret_move3 =
  840. {
  841. sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
  842. if (!(self.spawnflags & SECRET_OPEN_ONCE))
  843. {
  844. self.nextthink = self.ltime + self.wait;
  845. self.think = fd_secret_move4;
  846. }
  847. };
  848.  
  849. // Move backward...
  850. void () fd_secret_move4 =
  851. {
  852. sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
  853. SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);
  854. };
  855.  
  856. // Wait 1 second...
  857. void () fd_secret_move5 =
  858. {
  859. self.nextthink = self.ltime + 1.0;
  860. self.think = fd_secret_move6;
  861. sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
  862. };
  863.  
  864. void () fd_secret_move6 =
  865. {
  866. sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
  867. SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);
  868. };
  869.  
  870. void () fd_secret_done =
  871. {
  872. if (!self.targetname || self.spawnflags&SECRET_YES_SHOOT)
  873. {
  874. self.health = 10000;
  875. self.takedamage = DAMAGE_YES;
  876. self.th_pain = fd_secret_use;
  877. }
  878. sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
  879. };
  880.  
  881. void () secret_blocked =
  882. {
  883. if (time < self.attack_finished)
  884. return;
  885.  
  886. self.attack_finished = time + 0.5;
  887. // other.deathtype = "squish"; // QIP
  888. T_Damage (other, self, self, self.dmg, DTH_WORLD_SQUISH, FALSE, 1); // Supa
  889. };
  890.  
  891. /*
  892. ================
  893. secret_touch
  894.  
  895. Prints messages
  896. ================
  897. */
  898. void() secret_touch =
  899. {
  900. if (other.classname != "player")
  901. return;
  902. if (self.attack_finished > time)
  903. return;
  904.  
  905. self.attack_finished = time + 2;
  906.  
  907. if (self.message)
  908. {
  909. centerprint (other, self.message);
  910. sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
  911. }
  912. };
  913.  
  914.  
  915. /*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
  916. Basic secret door. Slides back, then to the side. Angle determines direction.
  917. wait = # of seconds before coming back
  918. 1st_left = 1st move is left of arrow
  919. 1st_down = 1st move is down from arrow
  920. always_shoot = even if targeted, keep shootable
  921. t_width = override WIDTH to move back (or height if going down)
  922. t_length = override LENGTH to move sideways
  923. "dmg" damage to inflict when blocked (2 default)
  924.  
  925. If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
  926. "sounds"
  927. 1) medieval
  928. 2) metal
  929. 3) base
  930. */
  931.  
  932. void () func_door_secret =
  933. {
  934. if (self.sounds == 0)
  935. self.sounds = 3;
  936. if (self.sounds == 1)
  937. {
  938. precache_sound ("doors/latch2.wav");
  939. precache_sound ("doors/winch2.wav");
  940. precache_sound ("doors/drclos4.wav");
  941. self.noise1 = "doors/latch2.wav";
  942. self.noise2 = "doors/winch2.wav";
  943. self.noise3 = "doors/drclos4.wav";
  944. }
  945. if (self.sounds == 2)
  946. {
  947. precache_sound ("doors/airdoor1.wav");
  948. precache_sound ("doors/airdoor2.wav");
  949. self.noise2 = "doors/airdoor1.wav";
  950. self.noise1 = "doors/airdoor2.wav";
  951. self.noise3 = "doors/airdoor2.wav";
  952. }
  953. if (self.sounds == 3)
  954. {
  955. precache_sound ("doors/basesec1.wav");
  956. precache_sound ("doors/basesec2.wav");
  957. self.noise2 = "doors/basesec1.wav";
  958. self.noise1 = "doors/basesec2.wav";
  959. self.noise3 = "doors/basesec2.wav";
  960. }
  961.  
  962. if (!self.dmg)
  963. self.dmg = 2;
  964.  
  965. // Magic formula...
  966. self.mangle = self.angles;
  967. self.angles = '0 0 0';
  968. self.solid = SOLID_BSP;
  969. self.movetype = MOVETYPE_PUSH;
  970. self.classname = "door";
  971. setmodel (self, self.model);
  972. setorigin (self, self.origin);
  973.  
  974. self.touch = secret_touch;
  975. self.blocked = secret_blocked;
  976. self.speed = 50;
  977. self.use = fd_secret_use;
  978. if ( !self.targetname || self.spawnflags&SECRET_YES_SHOOT)
  979. {
  980. self.health = 10000;
  981. self.takedamage = DAMAGE_YES;
  982. self.th_pain = fd_secret_use;
  983. self.th_die = fd_secret_use;
  984. self.nobleed = TRUE;// pOx - No bleed patch
  985. }
  986. self.oldorigin = self.origin;
  987. if (!self.wait)
  988. self.wait = 5; // 5 seconds before closing
  989. };
  990.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement