Advertisement
Guest User

rotate.qc

a guest
Mar 4th, 2012
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 29.07 KB | None | 0 0
  1. /*=======================================================//
  2. // mtfents.QC - CustomTF 3.2.OfN           - 30/1/2001 - //
  3. // by Sergio Fumaña Grunwaldt - OfteN [cp]               //
  4. =========================================================//
  5.  
  6.  I'll add rotate map entities support here
  7.  (some megatf maps use them like frontlin)
  8. _________________________________________________________
  9.  
  10.  This is the code of the hypnotic mission pack slighly
  11.  modified, it seems to work ok. I tested these entities
  12.  in frontlin and dyerfort.
  13.  
  14. =========================================================*/
  15.  
  16. #define STATE_ACTIVE      0
  17. #define STATE_INACTIVE    1
  18. #define STATE_SPEEDINGUP  2
  19. #define STATE_SLOWINGDOWN 3
  20.  
  21. #define STATE_CLOSED   4
  22. #define STATE_OPEN     5
  23. #define STATE_OPENING  6
  24. #define STATE_CLOSING  7
  25.  
  26. #define STATE_WAIT 0
  27. #define STATE_MOVE 1
  28. #define STATE_STOP 2
  29. #define STATE_FIND 3
  30. #define STATE_NEXT 4
  31.  
  32. #define OBJECT_ROTATE 0
  33. #define OBJECT_MOVEWALL  1
  34. #define OBJECT_SETORIGIN 2
  35.  
  36. #define TOGGLE   1
  37. #define START_ON 2
  38.  
  39. #define ROTATION    1
  40. #define ANGLES      2
  41. #define STOP        4
  42. #define NO_ROTATE   8
  43. #define DAMAGE      16
  44. #define MOVETIME    32
  45. #define SET_DAMAGE  64
  46.  
  47. #define VISIBLE     1
  48. #define TOUCH       2
  49. #define NONBLOCKING 4
  50.  
  51. #define STAYOPEN 1
  52.  
  53. //=========================
  54. //
  55. // SUB_NormalizeAngles
  56. // from hipsubs.qc
  57. //=========================
  58.  
  59. vector ( vector ang ) SUB_NormalizeAngles =
  60.    {
  61.    while( ang_x > 360 )
  62.       {
  63.       ang_x = ang_x - 360;
  64.       }
  65.    while( ang_x < 0 )
  66.       {
  67.       ang_x = ang_x + 360;
  68.       }
  69.  
  70.    while( ang_y > 360 )
  71.       {
  72.       ang_y = ang_y - 360;
  73.       }
  74.    while( ang_y < 0 )
  75.       {
  76.       ang_y = ang_y + 360;
  77.       }
  78.  
  79.    while( ang_z > 360 )
  80.       {
  81.       ang_z = ang_z - 360;
  82.       }
  83.    while( ang_z < 0 )
  84.       {
  85.       ang_z = ang_z + 360;
  86.       }
  87.  
  88.    return ang;
  89.    };
  90.  
  91.  
  92. //- ofn from triggers.qc of hip
  93. void( entity ent, float amount ) hurt_setdamage =
  94.    {
  95.    ent.dmg = amount;
  96.    if ( !amount )
  97.       {
  98.       ent.solid = #SOLID_NOT;
  99.       }
  100.    else
  101.       {
  102.       ent.solid = #SOLID_TRIGGER;
  103.       }
  104.    ent.nextthink = -1;
  105.    };
  106.  
  107.  
  108.  
  109. /*QUAKED info_rotate (0 0.5 0) (-4 -4 -4) (4 4 4)
  110. Used as the point of rotation for rotatable objects.
  111. */
  112. void() info_rotate =
  113. {
  114. // remove self after a little while, to make sure that entities that
  115. // have targeted it have had a chance to spawn
  116.    self.nextthink = time + 2;
  117.    self.think = SUB_Remove;
  118. };
  119.  
  120. void() RotateTargets =
  121.    {
  122.    local entity ent;
  123.    local vector vx;
  124.    local vector vy;
  125.    local vector vz;
  126.    local vector org;
  127.  
  128.    makevectors (self.angles);
  129.  
  130.    ent = find( world, targetname, self.target);
  131.    while( ent )
  132.       {
  133.       if ( ent.rotate_type == #OBJECT_SETORIGIN )
  134.          {
  135.          org = ent.oldorigin;
  136.          vx = ( v_forward * org_x );
  137.          vy = ( v_right   * org_y );
  138.          vy = vy * -1;
  139.          vz = ( v_up      * org_z );
  140.          ent.neworigin = vx + vy + vz;
  141.          setorigin( ent, ent.neworigin + self.origin );
  142.          }
  143.       else if ( ent.rotate_type == #OBJECT_ROTATE )
  144.          {
  145.          ent.angles = self.angles;
  146.          org = ent.oldorigin;
  147.          vx = ( v_forward * org_x );
  148.          vy = ( v_right   * org_y );
  149.          vy = vy * -1;
  150.          vz = ( v_up      * org_z );
  151.          ent.neworigin = vx + vy + vz;
  152.          setorigin( ent, ent.neworigin + self.origin );
  153.          }
  154.       else
  155.          {
  156.          org = ent.oldorigin;
  157.          vx = ( v_forward * org_x );
  158.          vy = ( v_right   * org_y );
  159.          vy = vy * -1;
  160.          vz = ( v_up      * org_z );
  161.          ent.neworigin = vx + vy + vz;
  162.          ent.neworigin = self.origin - self.oldorigin + (ent.neworigin - ent.oldorigin);
  163.          ent.velocity = (ent.neworigin-ent.origin)*25;
  164.          }
  165.       ent = find( ent, targetname, self.target);
  166.       }
  167.    };
  168.  
  169. void() RotateTargetsFinal =
  170.    {
  171.    local entity ent;
  172.  
  173.    ent = find( world, targetname, self.target);
  174.    while( ent )
  175.       {
  176.       ent.velocity = '0 0 0';
  177.       if ( ent.rotate_type == #OBJECT_ROTATE )
  178.          {
  179.          ent.angles = self.angles;
  180.          }
  181.       ent = find( ent, targetname, self.target);
  182.       }
  183.    };
  184.  
  185. void() SetTargetOrigin =
  186.    {
  187.    local entity ent;
  188.  
  189.    ent = find( world, targetname, self.target);
  190.    while( ent )
  191.       {
  192.       if ( ent.rotate_type == #OBJECT_MOVEWALL )
  193.          {
  194.          setorigin( ent, self.origin - self.oldorigin +
  195.             (ent.neworigin - ent.oldorigin) );
  196.          }
  197.       else
  198.          {
  199.          setorigin( ent, ent.neworigin + self.origin );
  200.          }
  201.       ent = find( ent, targetname, self.target);
  202.       }
  203.    };
  204.  
  205. void() LinkRotateTargets =
  206.    {
  207.    local entity ent;
  208.    local vector tempvec;
  209.  
  210.    self.oldorigin = self.origin;
  211.    ent = find( world, targetname, self.target);
  212.    while( ent )
  213.       {
  214.       if ( ent.classname == "rotate_object" )
  215.          {
  216.          ent.rotate_type = #OBJECT_ROTATE;
  217.          ent.oldorigin = ent.origin - self.oldorigin;
  218.          ent.neworigin = ent.origin - self.oldorigin;
  219.          ent.owner = self;
  220.          }
  221.       else if ( ent.classname == "func_movewall" )
  222.          {
  223.          ent.rotate_type = #OBJECT_MOVEWALL;
  224.          tempvec = ( ent.absmin + ent.absmax ) * 0.5;
  225.          ent.oldorigin = tempvec - self.oldorigin;
  226.          ent.neworigin = ent.oldorigin;
  227.          ent.owner = self;
  228.          }
  229.       else
  230.          {
  231.          ent.rotate_type = #OBJECT_SETORIGIN;
  232.          ent.oldorigin = ent.origin - self.oldorigin;
  233.          ent.neworigin = ent.origin - self.oldorigin;
  234.          }
  235.       ent = find (ent, targetname, self.target);
  236.       }
  237.    };
  238.  
  239. void( float amount ) SetDamageOnTargets =
  240.    {
  241.    local entity ent;
  242.  
  243.    ent = find( world, targetname, self.target);
  244.    while( ent )
  245.       {
  246.       if ( ent.classname == "trigger_hurt" )
  247.          {
  248.          hurt_setdamage( ent, amount );
  249.          }
  250.       else if ( ent.classname == "func_movewall" )
  251.          {
  252.          ent.dmg = amount;
  253.          }
  254.       ent = find( ent, targetname, self.target);
  255.       }
  256.    };
  257.  
  258.  
  259. //************************************************
  260. //
  261. // Simple continual rotatation
  262. //
  263. //************************************************
  264.  
  265. void() rotate_entity_think =
  266.    {
  267.    local float t;
  268.  
  269.    t = time - self.ltime;
  270.    self.ltime = time;
  271.  
  272.    if ( self.state == #STATE_SPEEDINGUP )
  273.       {
  274.       self.count = self.count + self.cnt * t;
  275.       if ( self.count > 1 )
  276.          {
  277.          self.count = 1;
  278.          }
  279.  
  280.       // get rate of rotation
  281.       t = t * self.count;
  282.       }
  283.    else if ( self.state == #STATE_SLOWINGDOWN )
  284.       {
  285.       self.count = self.count - self.cnt * t;
  286.       if ( self.count < 0 )
  287.          {
  288.          RotateTargetsFinal();
  289.          self.state = #STATE_INACTIVE;
  290.          self.think = SUB_Null;
  291.          return;
  292.          }
  293.  
  294.       // get rate of rotation
  295.       t = t * self.count;
  296.       }
  297.  
  298.    self.angles = self.angles + ( self.rotate * t );
  299.    self.angles = SUB_NormalizeAngles( self.angles );
  300.    RotateTargets();
  301.    self.nextthink = time + 0.02;
  302.    };
  303.  
  304. void() rotate_entity_use =
  305.    {
  306.    // change to alternate textures
  307.     self.frame = 1 - self.frame;
  308.  
  309.    if ( self.state == #STATE_ACTIVE )
  310.       {
  311.       if ( self.spawnflags & #TOGGLE )
  312.          {
  313.          if ( self.speed )
  314.             {
  315.             self.count = 1;
  316.             self.state = #STATE_SLOWINGDOWN;
  317.             }
  318.          else
  319.             {
  320.             self.state = #STATE_INACTIVE;
  321.             self.think = SUB_Null;
  322.             }
  323.          }
  324.       }
  325.    else if ( self.state == #STATE_INACTIVE )
  326.       {
  327.       self.think = rotate_entity_think;
  328.       self.nextthink = time + 0.02;
  329.       self.ltime = time;
  330.       if ( self.speed )
  331.          {
  332.          self.count = 0;
  333.          self.state = #STATE_SPEEDINGUP;
  334.          }
  335.       else
  336.          {
  337.          self.state = #STATE_ACTIVE;
  338.          }
  339.       }
  340.    else if ( self.state == #STATE_SPEEDINGUP )
  341.       {
  342.       if ( self.spawnflags & #TOGGLE )
  343.          {
  344.          self.state = #STATE_SLOWINGDOWN;
  345.          }
  346.       }
  347.    else
  348.       {
  349.       self.state = #STATE_SPEEDINGUP;
  350.       }
  351.    };
  352.  
  353. void() rotate_entity_firstthink =
  354.    {
  355.    LinkRotateTargets();
  356.    if ( self.spawnflags & #START_ON )
  357.       {
  358.       self.state = #STATE_ACTIVE;
  359.       self.think = rotate_entity_think;
  360.       self.nextthink = time + 0.02;
  361.       self.ltime = time;
  362.       }
  363.    else
  364.       {
  365.       self.state = #STATE_INACTIVE;
  366.       self.think = SUB_Null;
  367.       }
  368.    self.use = rotate_entity_use;
  369.    };
  370.  
  371. /*QUAKED func_rotate_entity (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE START_ON
  372. Creates an entity that continually rotates.  Can be toggled on and
  373. off if targeted.
  374.  
  375. TOGGLE = allows the rotation to be toggled on/off
  376.  
  377. START_ON = wether the entity is spinning when spawned.  If TOGGLE is 0, entity can be turned on, but not off.
  378.  
  379. If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
  380.  
  381. "rotate" is the rate to rotate.
  382. "target" is the center of rotation.
  383. "speed"  is how long the entity takes to go from standing still to full speed and vice-versa.
  384. */
  385.  
  386. void() func_rotate_entity =
  387.    {
  388.    self.solid    = #SOLID_NOT;
  389.    self.movetype = #MOVETYPE_NONE;
  390.  
  391.    setmodel (self, self.model);
  392.    setsize( self, self.mins, self.maxs );
  393.  
  394.    if ( self.speed != 0 )
  395.       {
  396.       self.cnt = 1 / self.speed;
  397.       }
  398.  
  399.    self.think = rotate_entity_firstthink;
  400.    self.nextthink = time + 0.1;
  401.    self.ltime = time;
  402.    };
  403.  
  404. //************************************************
  405. //
  406. // Train with rotation functionality
  407. //
  408. //************************************************
  409.  
  410. /*QUAKED path_rotate (0.5 0.3 0) (-8 -8 -8) (8 8 8) ROTATION ANGLES STOP NO_ROTATE DAMAGE MOVETIME SET_DAMAGE
  411.  Path for rotate_train.
  412.  
  413.  ROTATION tells train to rotate at rate specified by "rotate".  Use '0 0 0' to stop rotation.
  414.  
  415.  ANGLES tells train to rotate to the angles specified by "angles" while traveling to this path_rotate.  Use values < 0 or > 360 to guarantee that it turns in a certain direction.  Having this flag set automatically clears any rotation.
  416.  
  417.  STOP tells the train to stop and wait to be retriggered.
  418.  
  419.  NO_ROTATE tells the train to stop rotating when waiting to be triggered.
  420.  
  421.  DAMAGE tells the train to cause damage based on "dmg".
  422.  
  423.  MOVETIME tells the train to interpret "speed" as the length of time to take moving from one corner to another.
  424.  
  425.  SET_DAMAGE tells the train to set all targets damage to "dmg"
  426.  
  427.  "noise" contains the name of the sound to play when train stops.
  428.  "noise1" contains the name of the sound to play when train moves.
  429.  "event" is a target to trigger when train arrives at path_rotate.
  430. */
  431. void() path_rotate =
  432.    {
  433.    if ( self.noise )
  434.       {
  435.       precache_sound( self.noise );
  436.       }
  437.    if ( self.noise1 )
  438.       {
  439.       precache_sound( self.noise1 );
  440.       }
  441.    };
  442.  
  443.  
  444. void() rotate_train;
  445. void() rotate_train_next;
  446. void() rotate_train_find;
  447.  
  448. void() rotate_train_think =
  449.    {
  450.    local float t;
  451.    local float timeelapsed;
  452.  
  453.    t = time - self.ltime;
  454.    self.ltime = time;
  455.  
  456.    if ( ( self.endtime ) && ( time >= self.endtime ) )
  457.       {
  458.       self.endtime = 0;
  459.       if ( self.state == #STATE_MOVE )
  460.          {
  461.          setorigin(self, self.finaldest);
  462.          self.velocity = '0 0 0';
  463.          }
  464.  
  465.       if (self.think1)
  466.          self.think1();
  467.       }
  468.    else
  469.       {
  470.       timeelapsed = (time - self.cnt) * self.duration;
  471.       if ( timeelapsed > 1 )
  472.          timeelapsed = 1;
  473.       setorigin( self, self.dest1 + ( self.dest2 * timeelapsed ) );
  474.       }
  475.  
  476.    self.angles = self.angles + ( self.rotate * t );
  477.    self.angles = SUB_NormalizeAngles( self.angles );
  478.    RotateTargets();
  479.  
  480.    self.nextthink = time + 0.02;
  481.    };
  482.  
  483. void() rotate_train_use =
  484.    {
  485.    if (self.think1 != rotate_train_find)
  486.         {
  487.         if ( self.velocity != '0 0 0' )
  488.             return;     // already activated
  489.       if ( self.think1 )
  490.          {
  491.          self.think1();
  492.          }
  493.       }
  494.    };
  495.  
  496. void() rotate_train_wait =
  497.     {
  498.    self.state = #STATE_WAIT;
  499.  
  500.    if ( self.goalentity.noise )
  501.       {
  502.       sound (self, #CHAN_VOICE, self.goalentity.noise, 1, #ATTN_NORM);
  503.       }
  504.    else
  505.       {
  506.       sound (self, #CHAN_VOICE, self.noise, 1, #ATTN_NORM);
  507.       }
  508.    if ( self.goalentity.spawnflags & #ANGLES )
  509.       {
  510.       self.rotate = '0 0 0';
  511.       self.angles = self.finalangle;
  512.       }
  513.    if ( self.goalentity.spawnflags & #NO_ROTATE )
  514.       {
  515.       self.rotate = '0 0 0';
  516.       }
  517.    self.endtime = self.ltime + self.goalentity.wait;
  518.    self.think1 = rotate_train_next;
  519.    };
  520.  
  521. void() rotate_train_stop =
  522.     {
  523.    self.state = #STATE_STOP;
  524.  
  525.    if ( self.goalentity.noise )
  526.       {
  527.       sound (self, #CHAN_VOICE, self.goalentity.noise, 1, #ATTN_NORM);
  528.       }
  529.    else
  530.       {
  531.       sound (self, #CHAN_VOICE, self.noise, 1, #ATTN_NORM);
  532.       }
  533.    if ( self.goalentity.spawnflags & #ANGLES )
  534.       {
  535.       self.rotate = '0 0 0';
  536.       self.angles = self.finalangle;
  537.       }
  538.    if ( self.goalentity.spawnflags & #NO_ROTATE )
  539.       {
  540.       self.rotate = '0 0 0';
  541.       }
  542.  
  543.    self.dmg = 0;
  544.    self.think1 = rotate_train_next;
  545.    };
  546.  
  547. void() rotate_train_next =
  548. {
  549.    local entity targ;
  550.    local entity current;
  551.    local vector   vdestdelta;
  552.    local float    len, traveltime, div;
  553.    local string temp;
  554.  
  555.    self.state = #STATE_NEXT;
  556.  
  557.    current = self.goalentity;
  558.    targ = find (world, targetname, self.path );
  559.    if ( targ.classname != "path_rotate" )
  560.       objerror( "Next target is not path_rotate" );
  561.  
  562.    if ( self.goalentity.noise1 )
  563.       {
  564.       self.noise1 = self.goalentity.noise1;
  565.       }
  566.    sound (self, #CHAN_VOICE, self.noise1, 1, #ATTN_NORM);
  567.  
  568.    self.goalentity = targ;
  569.    self.path = targ.target;
  570.    if (!self.path )
  571.       objerror ("rotate_train_next: no next target");
  572.  
  573.    if ( targ.spawnflags & #STOP )
  574.       {
  575.       self.think1 = rotate_train_stop;
  576.       }
  577.    else if (targ.wait)
  578.         {
  579.       self.think1 = rotate_train_wait;
  580.       }
  581.     else
  582.         {
  583.       self.think1 = rotate_train_next;
  584.         }
  585.  
  586.    if ( current.event )
  587.       {
  588.       // Trigger any events that should happen at the corner.
  589.       temp = self.target;
  590.       self.target = current.event;
  591.       self.message = current.message;
  592.       SUB_UseTargets();
  593.       self.target = temp;
  594.       self.message = string_null;
  595.       }
  596.  
  597.    if ( current.spawnflags & #ANGLES )
  598.       {
  599.       self.rotate = '0 0 0';
  600.       self.angles = self.finalangle;
  601.       }
  602.  
  603.    if ( current.spawnflags & #ROTATION )
  604.       {
  605.       self.rotate = current.rotate;
  606.       }
  607.  
  608.    if ( current.spawnflags & #DAMAGE )
  609.       {
  610.       self.dmg = current.dmg;
  611.       }
  612.  
  613.    if ( current.spawnflags & #SET_DAMAGE )
  614.       {
  615.       SetDamageOnTargets( current.dmg );
  616.       }
  617.  
  618.    if ( current.speed == -1 )
  619.         {
  620.         // Warp to the next path_corner
  621.       setorigin( self, targ.origin );
  622.       self.endtime = self.ltime + 0.01;
  623.       SetTargetOrigin();
  624.  
  625.       if ( targ.spawnflags & #ANGLES )
  626.          {
  627.          self.angles = targ.angles;
  628.          }
  629.  
  630.       self.duration = 1;         // 1 / duration
  631.       self.cnt = time;           // start time
  632.       self.dest2 = '0 0 0';      // delta
  633.       self.dest1 = self.origin;  // original position
  634.       self.finaldest = self.origin;
  635.       }
  636.     else
  637.         {
  638.       self.state = #STATE_MOVE;
  639.  
  640.       self.finaldest = targ.origin;
  641.       if (self.finaldest == self.origin)
  642.          {
  643.          self.velocity = '0 0 0';
  644.          self.endtime = self.ltime + 0.1;
  645.  
  646.          self.duration = 1;        // 1 / duration
  647.          self.cnt = time;          // start time
  648.          self.dest2 = '0 0 0';     // delta
  649.          self.dest1 = self.origin; // original position
  650.          self.finaldest = self.origin;
  651.          return;
  652.          }
  653.       // set destdelta to the vector needed to move
  654.       vdestdelta = self.finaldest - self.origin;
  655.  
  656.       // calculate length of vector
  657.       len = vlen (vdestdelta);
  658.  
  659.       if ( current.spawnflags & #MOVETIME )
  660.          {
  661.          traveltime = current.speed;
  662.          }
  663.       else
  664.          {
  665.          // check if there's a speed change
  666.          if (current.speed>0)
  667.             self.speed = current.speed;
  668.  
  669.          if (!self.speed)
  670.             objerror("No speed is defined!");
  671.  
  672.          // divide by speed to get time to reach dest
  673.          traveltime = len / self.speed;
  674.          }
  675.  
  676.       if (traveltime < 0.1)
  677.          {
  678.          self.velocity = '0 0 0';
  679.          self.endtime = self.ltime + 0.1;
  680.          if ( targ.spawnflags & #ANGLES )
  681.             {
  682.             self.angles = targ.angles;
  683.             }
  684.          return;
  685.          }
  686.  
  687.       // qcc won't take vec/float
  688.       div = 1 / traveltime;
  689.  
  690.       if ( targ.spawnflags & #ANGLES )
  691.          {
  692.          self.finalangle = SUB_NormalizeAngles( targ.angles );
  693.          self.rotate = ( targ.angles - self.angles ) * div;
  694.          }
  695.  
  696.       // set endtime to trigger a think when dest is reached
  697.       self.endtime = self.ltime + traveltime;
  698.  
  699.       // scale the destdelta vector by the time spent traveling to get velocity
  700.       self.velocity = vdestdelta * div;
  701.  
  702.       self.duration = div;      // 1 / duration
  703.       self.cnt = time;          // start time
  704.       self.dest2 = vdestdelta;  // delta
  705.       self.dest1 = self.origin; // original position
  706.       }
  707.    };
  708.  
  709. void() rotate_train_find =
  710.    {
  711.    local entity targ;
  712.  
  713.    self.state = #STATE_FIND;
  714.  
  715.    LinkRotateTargets();
  716.  
  717.    // the first target is the point of rotation.
  718.    // the second target is the path.
  719.    targ = find ( world, targetname, self.path);
  720.    if ( targ.classname != "path_rotate" )
  721.       objerror( "Next target is not path_rotate" );
  722.  
  723.    // Save the current entity
  724.    self.goalentity = targ;
  725.  
  726.    if ( targ.spawnflags & #ANGLES )
  727.       {
  728.       self.angles = targ.angles;
  729.       self.finalangle = SUB_NormalizeAngles( targ.angles );
  730.       }
  731.  
  732.    self.path = targ.target;
  733.    setorigin (self, targ.origin );
  734.    SetTargetOrigin();
  735.    RotateTargetsFinal();
  736.    self.think1 = rotate_train_next;
  737.    if (!self.targetname)
  738.       {
  739.       // not triggered, so start immediately
  740.       self.endtime = self.ltime + 0.1;
  741.       }
  742.    else
  743.       {
  744.       self.endtime = 0;
  745.       }
  746.  
  747.    self.duration = 1;        // 1 / duration
  748.    self.cnt = time;          // start time
  749.    self.dest2 = '0 0 0';     // delta
  750.    self.dest1 = self.origin; // original position
  751.    };
  752.  
  753. /*QUAKED func_rotate_train (0 .5 .8) (-8 -8 -8) (8 8 8)
  754. In path_rotate, set speed to be the new speed of the train after it reaches
  755. the path change.  If speed is -1, the train will warp directly to the next
  756. path change after the specified wait time.  If MOVETIME is set on the
  757. path_rotate, the train to interprets "speed" as the length of time to
  758. take moving from one corner to another.
  759.  
  760. "noise" contains the name of the sound to play when train stops.
  761. "noise1" contains the name of the sound to play when train moves.
  762. Both "noise" and "noise1" defaults depend upon "sounds" variable and
  763. can be overridden by the "noise" and "noise1" variable in path_rotate.
  764.  
  765. Also in path_rotate, if STOP is set, the train will wait until it is
  766. retriggered before moving on to the next goal.
  767.  
  768. Trains are moving platforms that players can ride.
  769. "path" specifies the first path_rotate and is the starting position.
  770. If the train is the target of a button or trigger, it will not begin moving until activated.
  771. The func_rotate_train entity is the center of rotation of all objects targeted by it.
  772.  
  773. If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
  774.  
  775. speed   default 100
  776. dmg      default  0
  777. sounds
  778. 1) ratchet metal
  779. */
  780.  
  781. void() rotate_train =
  782.    {
  783.    objerror ("rotate_train entities should be changed to rotate_object with\nfunc_rotate_train controllers\n");
  784.    };
  785.  
  786. void() func_rotate_train =
  787.    {
  788.    if (!self.speed)
  789.         self.speed = 100;
  790.     if (!self.target)
  791.       objerror ("rotate_train without a target");
  792.  
  793.    if ( !self.noise )
  794.       {
  795.       if (self.sounds == 0)
  796.          {
  797.          self.noise = ("misc/null.wav");
  798.          }
  799.  
  800.       if (self.sounds == 1)
  801.          {
  802.          self.noise = ("plats/train2.wav");
  803.          }
  804.       }
  805.    if ( !self.noise1 )
  806.       {
  807.       if (self.sounds == 0)
  808.          {
  809.          self.noise1 = ("misc/null.wav");
  810.          }
  811.       if (self.sounds == 1)
  812.          {
  813.          self.noise1 = ("plats/train1.wav");
  814.          }
  815.       }
  816.  
  817.    precache_sound( self.noise );
  818.    precache_sound( self.noise1 );
  819.  
  820.    self.cnt = 1;
  821.    self.solid    = #SOLID_NOT;
  822.    self.movetype = #MOVETYPE_STEP;
  823.    self.use = rotate_train_use;
  824.  
  825.    setmodel (self, self.model);
  826.    setsize (self, self.mins, self.maxs);
  827.     setorigin (self, self.origin);
  828.  
  829. // start trains on the second frame, to make sure their targets have had
  830. // a chance to spawn
  831.    self.ltime = time;
  832.     self.nextthink = self.ltime + 0.1;
  833.    self.endtime = self.ltime + 0.1;
  834.    self.think = rotate_train_think;
  835.    self.think1 = rotate_train_find;
  836.    self.state = #STATE_FIND;
  837.  
  838.    self.duration = 1;        // 1 / duration
  839.    self.cnt = 0.1;           // start time
  840.    self.dest2 = '0 0 0';     // delta
  841.    self.dest1 = self.origin; // original position
  842.  
  843.  
  844.    self.flags = self.flags | #FL_ONGROUND;
  845.    };
  846.  
  847. //************************************************
  848. //
  849. // Moving clip walls
  850. //
  851. //************************************************
  852.  
  853. void() rotate_door_reversedirection;
  854. void() rotate_door_group_reversedirection;
  855.  
  856. void() movewall_touch =
  857.    {
  858.    if (time < self.owner.attack_finished)
  859.         return;
  860.  
  861.    if ( self.dmg )
  862.       {
  863.       T_Damage (other, self, self.owner, self.dmg);
  864.       self.owner.attack_finished = time + 0.5;
  865.       }
  866.    else if ( self.owner.dmg )
  867.       {
  868.       T_Damage (other, self, self.owner, self.owner.dmg);
  869.       self.owner.attack_finished = time + 0.5;
  870.       }
  871.    };
  872.  
  873. void() movewall_blocked =
  874.    {
  875.    local entity temp;
  876.  
  877.    if (time < self.owner.attack_finished)
  878.         return;
  879.  
  880.    self.owner.attack_finished = time + 0.5;
  881.  
  882.    if ( self.owner.classname == "func_rotate_door" )
  883.       {
  884.       temp = self;
  885.       self = self.owner;
  886.       rotate_door_group_reversedirection();
  887.       self = temp;
  888.       }
  889.  
  890.    if ( self.dmg )
  891.       {
  892.       T_Damage (other, self, self.owner, self.dmg);
  893.       self.owner.attack_finished = time + 0.5;
  894.       }
  895.    else if ( self.owner.dmg )
  896.       {
  897.       T_Damage (other, self, self.owner, self.owner.dmg);
  898.       self.owner.attack_finished = time + 0.5;
  899.       }
  900.    };
  901.  
  902. void() movewall_think =
  903.    {
  904.    self.ltime = time;
  905.    self.nextthink = time + 0.02;
  906.    };
  907.  
  908. /*QUAKED func_movewall (0 .5 .8) ? VISIBLE TOUCH NONBLOCKING
  909. Used to emulate collision on rotating objects.
  910.  
  911. VISIBLE causes brush to be displayed.
  912.  
  913. TOUCH specifies whether to cause damage when touched by player.
  914.  
  915. NONBLOCKING makes the brush non-solid.  This is useless if VISIBLE is set.
  916.  
  917. "dmg" specifies the damage to cause when touched or blocked.
  918. */
  919. void() func_movewall =
  920.    {
  921.    self.angles = '0 0 0';
  922.    self.movetype = #MOVETYPE_PUSH;
  923.    if ( self.spawnflags & #NONBLOCKING )
  924.       {
  925.       self.solid = #SOLID_NOT;
  926.       }
  927.    else
  928.       {
  929.       self.solid = #SOLID_BSP;
  930.       self.blocked = movewall_blocked;
  931.       }
  932.    if ( self.spawnflags & #TOUCH )
  933.       {
  934.       self.touch = movewall_touch;
  935.       }
  936.    setmodel (self,self.model);
  937.    if ( !( self.spawnflags & #VISIBLE ) )
  938.       {
  939.       self.model = string_null;
  940.       }
  941.    self.think = movewall_think;
  942.    self.nextthink = time + 0.02;
  943.    self.ltime = time;
  944.    };
  945.  
  946. /*QUAKED rotate_object (0 .5 .8) ?
  947. This defines an object to be rotated.  Used as the target of func_rotate_door.
  948. */
  949. void() rotate_object =
  950.    {
  951.    self.classname = "rotate_object";
  952.    self.solid = #SOLID_NOT;
  953.    self.movetype = #MOVETYPE_NONE;
  954.    setmodel (self,self.model);
  955.    setsize( self, self.mins, self.maxs );
  956.    self.think = SUB_Null;
  957.    };
  958.  
  959. //************************************************
  960. //
  961. // Rotating doors
  962. //
  963. //************************************************
  964.  
  965. void() rotate_door_think2 =
  966.    {
  967.    local float t;
  968.  
  969.    t = time - self.ltime;
  970.    self.ltime = time;
  971.  
  972.    // change to alternate textures
  973.    self.frame = 1 - self.frame;
  974.  
  975.    self.angles = self.dest;
  976.  
  977.    if ( self.state == #STATE_OPENING )
  978.       {
  979.       self.state = #STATE_OPEN;
  980.       }
  981.    else
  982.       {
  983.       if ( self.spawnflags & #STAYOPEN )
  984.          {
  985.          rotate_door_group_reversedirection();
  986.          return;
  987.          }
  988.       self.state = #STATE_CLOSED;
  989.       }
  990.  
  991.    sound(self, #CHAN_VOICE, self.noise3, 1, #ATTN_NORM);
  992.    self.think = SUB_Null;
  993.  
  994.    RotateTargetsFinal();
  995.    };
  996.  
  997. void() rotate_door_think =
  998.    {
  999.    local float t;
  1000.  
  1001.    t = time - self.ltime;
  1002.    self.ltime = time;
  1003.  
  1004.    if ( time < self.endtime )
  1005.       {
  1006.       self.angles = self.angles + ( self.rotate * t );
  1007.       RotateTargets();
  1008.       }
  1009.    else
  1010.       {
  1011.       self.angles = self.dest;
  1012.       RotateTargets();
  1013.       self.think = rotate_door_think2;
  1014.       }
  1015.  
  1016.    self.nextthink = time + 0.01;
  1017.    };
  1018.  
  1019. void() rotate_door_reversedirection =
  1020.    {
  1021.    local vector start;
  1022.  
  1023.    // change to alternate textures
  1024.     self.frame = 1 - self.frame;
  1025.  
  1026.    if ( self.state == #STATE_CLOSING )
  1027.       {
  1028.       start = self.dest1;
  1029.       self.dest = self.dest2;
  1030.       self.state = #STATE_OPENING;
  1031.       }
  1032.    else
  1033.       {
  1034.       start = self.dest2;
  1035.       self.dest = self.dest1;
  1036.       self.state = #STATE_CLOSING;
  1037.       }
  1038.  
  1039.    sound(self, #CHAN_VOICE, self.noise2, 1, #ATTN_NORM);
  1040.  
  1041.    self.rotate = ( self.dest - start ) * ( 1 / self.speed );
  1042.    self.think = rotate_door_think;
  1043.    self.nextthink = time + 0.02;
  1044.    self.endtime = time + self.speed - ( self.endtime - time );
  1045.    self.ltime = time;
  1046.    };
  1047.  
  1048. void() rotate_door_group_reversedirection =
  1049.    {
  1050.    local string name;
  1051.  
  1052.    // tell all associated rotaters to reverse direction
  1053.    if ( self.group )
  1054.       {
  1055.       name = self.group;
  1056.       self = find( world, group, name);
  1057.       while( self )
  1058.          {
  1059.          rotate_door_reversedirection();
  1060.          self = find( self, group, name);
  1061.          }
  1062.       }
  1063.    else
  1064.       {
  1065.       rotate_door_reversedirection();
  1066.       }
  1067.    };
  1068.  
  1069. void() rotate_door_use =
  1070.    {
  1071.    //local entity t;
  1072.    local vector start;
  1073.  
  1074.    if ( ( self.state != #STATE_OPEN ) && ( self.state != #STATE_CLOSED ) )
  1075.       return;
  1076.  
  1077.    if ( !self.cnt )
  1078.       {
  1079.       self.cnt = 1;
  1080.       LinkRotateTargets();
  1081.       }
  1082.  
  1083.    // change to alternate textures
  1084.     self.frame = 1 - self.frame;
  1085.  
  1086.    if ( self.state == #STATE_CLOSED )
  1087.       {
  1088.       start = self.dest1;
  1089.       self.dest = self.dest2;
  1090.       self.state = #STATE_OPENING;
  1091.       }
  1092.    else
  1093.       {
  1094.       start = self.dest2;
  1095.       self.dest = self.dest1;
  1096.       self.state = #STATE_CLOSING;
  1097.       }
  1098.  
  1099.    sound(self, #CHAN_VOICE, self.noise2, 1, #ATTN_NORM);
  1100.  
  1101.    self.rotate = ( self.dest - start ) * ( 1 / self.speed );
  1102.    self.think = rotate_door_think;
  1103.    self.nextthink = time + 0.01;
  1104.    self.endtime = time + self.speed;
  1105.    self.ltime = time;
  1106.    };
  1107.  
  1108.  
  1109. /*QUAKED func_rotate_door (0 .5 .8) (-8 -8 -8) (8 8 8) STAYOPEN
  1110. Creates a door that rotates between two positions around a point of
  1111. rotation each time it's triggered.
  1112.  
  1113. STAYOPEN tells the door to reopen after closing.  This prevents a trigger-
  1114. once door from closing again when it's blocked.
  1115.  
  1116. "dmg" specifies the damage to cause when blocked.  Defaults to 2.  Negative numbers indicate no damage.
  1117. "speed" specifies how the time it takes to rotate
  1118.  
  1119. "sounds"
  1120. 1) medieval (default)
  1121. 2) metal
  1122. 3) base
  1123. */
  1124.  
  1125. void() func_rotate_door =
  1126.    {
  1127.    if (!self.target)
  1128.       {
  1129.       objerror( "rotate_door without target." );
  1130.       }
  1131.  
  1132.    self.dest1 = '0 0 0';
  1133.    self.dest2 = self.angles;
  1134.    self.angles = self.dest1;
  1135.  
  1136.    // default to 2 seconds
  1137.    if ( !self.speed )
  1138.       {
  1139.       self.speed = 2;
  1140.       }
  1141.  
  1142.    self.cnt = 0;
  1143.  
  1144.    if (!self.dmg)
  1145.         self.dmg = 2;
  1146.    else if ( self.dmg < 0 )
  1147.       {
  1148.       self.dmg = 0;
  1149.       }
  1150.  
  1151.    if (self.sounds == 0)
  1152.    //   self.sounds = 1; // OfN - allow custom sounds
  1153.    {
  1154.         precache_sound (self.noise1);
  1155.         precache_sound (self.noise2);
  1156.         precache_sound (self.noise3);
  1157.         //self.noise1 = "doors/latch2.wav";
  1158.         //self.noise2 = "doors/winch2.wav";
  1159.         //self.noise3 = "doors/drclos4.wav";
  1160.    }
  1161.  
  1162.     if (self.sounds == 1)
  1163.     {
  1164.         precache_sound ("doors/latch2.wav");
  1165.         precache_sound ("doors/winch2.wav");
  1166.         precache_sound ("doors/drclos4.wav");
  1167.         self.noise1 = "doors/latch2.wav";
  1168.         self.noise2 = "doors/winch2.wav";
  1169.         self.noise3 = "doors/drclos4.wav";
  1170.     }
  1171.     if (self.sounds == 2)
  1172.     {
  1173.         precache_sound ("doors/airdoor1.wav");
  1174.         precache_sound ("doors/airdoor2.wav");
  1175.         self.noise2 = "doors/airdoor1.wav";
  1176.         self.noise1 = "doors/airdoor2.wav";
  1177.         self.noise3 = "doors/airdoor2.wav";
  1178.     }
  1179.     if (self.sounds == 3)
  1180.     {
  1181.         precache_sound ("doors/basesec1.wav");
  1182.         precache_sound ("doors/basesec2.wav");
  1183.         self.noise2 = "doors/basesec1.wav";
  1184.         self.noise1 = "doors/basesec2.wav";
  1185.         self.noise3 = "doors/basesec2.wav";
  1186.     }
  1187.  
  1188.    self.solid = #SOLID_NOT;
  1189.    self.movetype = #MOVETYPE_NONE;
  1190.    setmodel (self, self.model);
  1191.    setorigin( self, self.origin );
  1192.    setsize( self, self.mins, self.maxs );
  1193.    self.state = #STATE_CLOSED;
  1194.    self.use = rotate_door_use;
  1195.    self.think = SUB_Null;
  1196.    };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement