Advertisement
techforce

Reaperbot full code

Sep 9th, 2011
559
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Clone C 123.67 KB | None | 0 0
  1. float (entity targ) botrange;
  2.  
  3. vector (vector src, vector trg, float invMvel) leadtarget =
  4. {
  5.     local vector tg;
  6.     local vector lead;
  7.  
  8.     lead = ((self.enemy.velocity * invMvel) * vlen ((trg - src)));
  9.     tg = (trg + lead);
  10.     if ((self.weapon == IT_ROCKET_LAUNCHER))
  11.     {
  12.         if ((self.skil > FL_SWIM))
  13.         {
  14.             traceline (src, tg, TRUE, self);
  15.             if ((trace_fraction != TRUE))
  16.             {
  17.                 tg = (tg - (lead * 0.5));
  18.                 traceline (src, tg, TRUE, self);
  19.                 if ((trace_fraction != TRUE))
  20.                 {
  21.                     tg = (tg - (lead * 0.5));
  22.                 }
  23.             }
  24.         }
  25.     }
  26.     return (tg);
  27. };
  28.  
  29. vector (vector trg) adjustgrenade =
  30. {
  31.     local vector tg;
  32.     local vector tgxy;
  33.     local vector selfxy;
  34.     local vector lead;
  35.     local float xypct;
  36.  
  37.     tg = trg;
  38.     tgxy = tg;
  39.     tgxy_z = FALSE;
  40.     selfxy = self.origin;
  41.     selfxy_z = FALSE;
  42.     xypct = (vlen ((tgxy - selfxy)) * INVGRENADELEVELDIST);
  43.     if ((xypct > TRUE))
  44.     {
  45.         if ((xypct < 12))
  46.         {
  47.             tg_z = (tg_z + (GRENADEMAXHEIGHT * (xypct - TRUE)));
  48.         }
  49.     }
  50.     else
  51.     {
  52.         tg_z = (tg_z - (GRENADEMAXHEIGHT * (TRUE - xypct)));
  53.     }
  54.     return (tg);
  55. };
  56.  
  57. vector () botaim =
  58. {
  59.     local vector dir;
  60.     local vector tg;
  61.     local vector lead;
  62.     local vector src;
  63.     local float sk;
  64.     local float rnd;
  65.  
  66.     if (REBOUND)
  67.     {
  68.         tg = REBOUNDSPOT;
  69.     }
  70.     else
  71.     {
  72.         src = self.origin;
  73.         if ((self.weapon & ((IT_ROCKET_LAUNCHER + IT_SUPER_NAILGUN) + IT_NAILGUN)))
  74.         {
  75.             src = (src + '0 0 16');
  76.         }
  77.         tg = self.enemy.origin;
  78.         traceline (src, tg, TRUE, self);
  79.         if ((trace_fraction != TRUE))
  80.         {
  81.             tg = (tg + self.enemy.view_ofs);
  82.         }
  83.         if ((self.skil > TRUE))
  84.         {
  85.             if ((self.weapon & IT_ROCKET_LAUNCHER))
  86.             {
  87.                 tg = leadtarget (src, tg, 0.001);
  88.                 if ((self.origin_z >= self.enemy.origin_z))
  89.                 {
  90.                     rnd = ((random () * 3.5) + TRUE);
  91.                     if ((self.skil > rnd))
  92.                     {
  93.                         tg_z = ((tg_z + self.enemy.mins_z) + FL_SWIM);
  94.                         traceline (src, tg, TRUE, self);
  95.                         if ((trace_fraction != TRUE))
  96.                         {
  97.                             tg_z = ((tg_z - self.enemy.mins_z) - MOVETYPE_WALK);
  98.                         }
  99.                     }
  100.                 }
  101.             }
  102.             else
  103.             {
  104.                 if ((self.weapon & IT_GRENADE_LAUNCHER))
  105.                 {
  106.                     tg = leadtarget (src, tg, 0.00167);
  107.                 }
  108.                 else
  109.                 {
  110.                     if (((self.weapon & IT_SUPER_NAILGUN) || (self.weapon & IT_NAILGUN)))
  111.                     {
  112.                         rnd = (random () * 0.0016);
  113.                         tg = leadtarget (src, tg, rnd);
  114.                     }
  115.                 }
  116.             }
  117.         }
  118.     }
  119.     if ((self.weapon == IT_GRENADE_LAUNCHER))
  120.     {
  121.         tg = adjustgrenade (tg);
  122.     }
  123.     sk = self.skil;
  124.     if ((self.weapon == IT_LIGHTNING))
  125.     {
  126.         if ((sk > 2.5))
  127.         {
  128.             sk = 2.5;
  129.         }
  130.     }
  131.     if ((sk < MOVETYPE_WALK))
  132.     {
  133.         lead = (self.enemy.origin - self.enemy.oldorigin);
  134.         lead = (((lead * (MOVETYPE_WALK - sk)) * 3.5) * (random () - 0.5));
  135.         tg = (tg + lead);
  136.     }
  137.     dir = normalize ((tg - self.origin));
  138.     if ((sk < MOVETYPE_WALK))
  139.     {
  140.         dir = (dir + (((MOVETYPE_WALK - sk) * crandom ()) * '0.06 0 0'));
  141.         dir = (dir + (((MOVETYPE_WALK - sk) * crandom ()) * '0 0.06 0'));
  142.     }
  143.     dir = normalize (dir);
  144.     return (dir);
  145. };
  146.  
  147. float () CheckBotAttack =
  148. {
  149.     local vector spot1;
  150.     local vector spot2;
  151.     local entity targ;
  152.  
  153.     targ = self.enemy;
  154.     if ((time < self.attack_finished))
  155.     {
  156.         return (FALSE);
  157.     }
  158.     spot1 = (self.origin + self.view_ofs);
  159.     spot2 = (targ.origin + targ.view_ofs);
  160.     traceline (spot1, spot2, FALSE, self);
  161.     if ((trace_ent != targ))
  162.     {
  163.         return (FALSE);
  164.     }
  165.     if ((trace_inopen && trace_inwater))
  166.     {
  167.         spot2 = targ.origin;
  168.         traceline (spot1, spot2, FALSE, self);
  169.         if ((trace_inopen && trace_inwater))
  170.         {
  171.             return (FALSE);
  172.         }
  173.     }
  174.     self.attack_state = AS_MELEE;
  175.     return (TRUE);
  176. };
  177.  
  178. float () W_BestBotWeapon =
  179. {
  180.     local float it;
  181.     local float rng;
  182.     local float wlevel;
  183.  
  184.     it = self.items;
  185.     rng = botrange (self.enemy);
  186.     if ((rng != RANGE_MELEE))
  187.     {
  188.         if (((self.ammo_rockets >= TRUE) && (it & IT_ROCKET_LAUNCHER)))
  189.         {
  190.             return (IT_ROCKET_LAUNCHER);
  191.         }
  192.     }
  193.     if (((self.ammo_cells >= TRUE) && (it & IT_LIGHTNING)))
  194.     {
  195.         if (((rng == RANGE_MELEE) || (rng == RANGE_NEAR)))
  196.         {
  197.             wlevel = CheckWaterLevel ();
  198.             if ((wlevel < FL_SWIM))
  199.             {
  200.                 return (IT_LIGHTNING);
  201.             }
  202.             if ((self.items & IT_INVULNERABILITY))
  203.             {
  204.                 return (IT_LIGHTNING);
  205.             }
  206.         }
  207.     }
  208.     if (((self.ammo_nails >= FL_SWIM) && (it & IT_SUPER_NAILGUN)))
  209.     {
  210.         return (IT_SUPER_NAILGUN);
  211.     }
  212.     if ((rng == RANGE_NEAR))
  213.     {
  214.         if (((self.ammo_rockets >= TRUE) && (it & IT_GRENADE_LAUNCHER)))
  215.         {
  216.             if ((self.enemy.origin_z < (self.origin_z + 175)))
  217.             {
  218.                 return (IT_GRENADE_LAUNCHER);
  219.             }
  220.         }
  221.     }
  222.     if (((rng == RANGE_NEAR) || (rng == RANGE_MELEE)))
  223.     {
  224.         if (((self.ammo_shells >= FL_SWIM) && (it & IT_SUPER_SHOTGUN)))
  225.         {
  226.             return (IT_SUPER_SHOTGUN);
  227.         }
  228.     }
  229.     if (((self.ammo_nails >= TRUE) && (it & IT_NAILGUN)))
  230.     {
  231.         return (IT_NAILGUN);
  232.     }
  233.     if (((self.ammo_shells >= TRUE) && (it & IT_SHOTGUN)))
  234.     {
  235.         return (IT_SHOTGUN);
  236.     }
  237.     return (IT_AXE);
  238. };
  239.  
  240. float () W_BestHeldWeapon =
  241. {
  242.     local float it;
  243.     local float wlevel;
  244.  
  245.     it = self.items;
  246.     if (((self.ammo_rockets >= TRUE) && (it & IT_ROCKET_LAUNCHER)))
  247.     {
  248.         return (IT_ROCKET_LAUNCHER);
  249.     }
  250.     if (((self.ammo_cells >= TRUE) && (it & IT_LIGHTNING)))
  251.     {
  252.         wlevel = CheckWaterLevel ();
  253.         if ((wlevel < FL_SWIM))
  254.         {
  255.             return (IT_LIGHTNING);
  256.         }
  257.         if ((self.items & IT_INVULNERABILITY))
  258.         {
  259.             return (IT_LIGHTNING);
  260.         }
  261.     }
  262.     if (((self.ammo_nails >= FL_SWIM) && (it & IT_SUPER_NAILGUN)))
  263.     {
  264.         return (IT_SUPER_NAILGUN);
  265.     }
  266.     if (((self.ammo_rockets >= TRUE) && (it & IT_GRENADE_LAUNCHER)))
  267.     {
  268.         if ((self.enemy.origin_z < (self.origin_z + 175)))
  269.         {
  270.             return (IT_GRENADE_LAUNCHER);
  271.         }
  272.     }
  273.     if (((self.ammo_shells >= FL_SWIM) && (it & IT_SUPER_SHOTGUN)))
  274.     {
  275.         return (IT_SUPER_SHOTGUN);
  276.     }
  277.     if (((self.ammo_nails >= TRUE) && (it & IT_NAILGUN)))
  278.     {
  279.         return (IT_NAILGUN);
  280.     }
  281.     if (((self.ammo_shells >= TRUE) && (it & IT_SHOTGUN)))
  282.     {
  283.         return (IT_SHOTGUN);
  284.     }
  285.     return (IT_AXE);
  286. };
  287. void () bot_axe1;
  288. void () bot_axeb1;
  289. void () bot_axec1;
  290. void () bot_axed1;
  291. void () bot_shot1;
  292. void () bot_nail1;
  293. void () bot_light1;
  294. void () bot_rocket1;
  295.  
  296. void () W_BotAttack =
  297. {
  298.     local float r;
  299.     local float addt;
  300.  
  301.     if (!W_CheckNoAmmo ())
  302.     {
  303.         return;
  304.     }
  305.     if ((time < self.attack_finished))
  306.     {
  307.         return;
  308.     }
  309.     addt = FALSE;
  310.     if ((self.skil < MOVETYPE_WALK))
  311.     {
  312.         addt = (((MOVETYPE_WALK - self.skil) * random ()) * 0.35);
  313.     }
  314.     if ((self.skil < TRUE))
  315.     {
  316.         addt = (addt + (random () * 0.3));
  317.     }
  318.     makevectors (self.v_angle);
  319.     self.show_hostile = (time + TRUE);
  320.     if ((self.weapon == IT_AXE))
  321.     {
  322.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", TRUE, ATTN_NORM);
  323.         r = random ();
  324.         if ((r < 0.25))
  325.         {
  326.             bot_axe1 ();
  327.         }
  328.         else
  329.         {
  330.             if ((r < 0.5))
  331.             {
  332.                 bot_axeb1 ();
  333.             }
  334.             else
  335.             {
  336.                 if ((r < 0.75))
  337.                 {
  338.                     bot_axec1 ();
  339.                 }
  340.                 else
  341.                 {
  342.                     bot_axed1 ();
  343.                 }
  344.             }
  345.         }
  346.         self.attack_finished = ((time + 0.5) + addt);
  347.     }
  348.     else
  349.     {
  350.         if ((self.weapon == IT_SHOTGUN))
  351.         {
  352.             bot_shot1 ();
  353.             W_FireShotgun ();
  354.             self.attack_finished = ((time + 0.5) + addt);
  355.         }
  356.         else
  357.         {
  358.             if ((self.weapon == IT_SUPER_SHOTGUN))
  359.             {
  360.                 bot_shot1 ();
  361.                 W_FireSuperShotgun ();
  362.                 self.attack_finished = ((time + 0.7) + addt);
  363.             }
  364.             else
  365.             {
  366.                 if ((self.weapon == IT_NAILGUN))
  367.                 {
  368.                     self.think = bot_nail1;
  369.                 }
  370.                 else
  371.                 {
  372.                     if ((self.weapon == IT_SUPER_NAILGUN))
  373.                     {
  374.                         self.think = bot_nail1;
  375.                     }
  376.                     else
  377.                     {
  378.                         if ((self.weapon == IT_GRENADE_LAUNCHER))
  379.                         {
  380.                             bot_rocket1 ();
  381.                             W_FireGrenade ();
  382.                             self.attack_finished = ((time + 0.6) + addt);
  383.                         }
  384.                         else
  385.                         {
  386.                             if ((self.weapon == IT_ROCKET_LAUNCHER))
  387.                             {
  388.                                 bot_rocket1 ();
  389.                                 W_FireRocket ();
  390.                                 self.attack_finished = ((time + 0.8) + addt);
  391.                             }
  392.                             else
  393.                             {
  394.                                 if ((self.weapon == IT_LIGHTNING))
  395.                                 {
  396.                                     self.think = bot_light1;
  397.                                     self.attack_finished = (time + 0.1);
  398.                                     sound (self, CHAN_AUTO, "weapons/lstart.wav", TRUE, ATTN_NORM);
  399.                                 }
  400.                             }
  401.                         }
  402.                     }
  403.                 }
  404.             }
  405.         }
  406.     }
  407. };
  408. void () bot_rebound1;
  409.  
  410. float () CheckReboundAttack =
  411. {
  412.     local vector spot1;
  413.     local vector spot2;
  414.     local vector dir;
  415.     local float dist;
  416.     local float mel;
  417.  
  418.     if ((self.skil < TRUE))
  419.     {
  420.         return (FALSE);
  421.     }
  422.     if ((self.attack_finished > time))
  423.     {
  424.         return (FALSE);
  425.     }
  426.     if (!(self.items & (IT_ROCKET_LAUNCHER + IT_GRENADE_LAUNCHER)))
  427.     {
  428.         return (FALSE);
  429.     }
  430.     if ((self.ammo_rockets < MOVETYPE_WALK))
  431.     {
  432.         return (FALSE);
  433.     }
  434.     spot1 = self.origin;
  435.     spot2 = self.goalentity.origin;
  436.     traceline (spot1, spot2, FALSE, self);
  437.     if ((trace_fraction < TRUE))
  438.     {
  439.         return (FALSE);
  440.     }
  441.     dir = normalize ((self.goalentity.origin - self.origin));
  442.     spot2 = (spot2 + (200 * dir));
  443.     traceline (spot1, spot2, TRUE, self);
  444.     if ((trace_fraction == TRUE))
  445.     {
  446.         if ((self.origin_z < self.goalentity.origin_z))
  447.         {
  448.             return (FALSE);
  449.         }
  450.         spot2 = self.goalentity.origin;
  451.         spot2_z = (dropline (spot2) + MOVETYPE_WALK);
  452.         traceline (spot1, spot2, TRUE, self);
  453.         if ((trace_fraction != TRUE))
  454.         {
  455.             return (FALSE);
  456.         }
  457.     }
  458.     else
  459.     {
  460.         spot2 = (self.goalentity.origin + ((200 * dir) * trace_fraction));
  461.     }
  462.     dist = vlen ((self.enemy.origin - spot2));
  463.     mel = 200;
  464.     if ((self.items & IT_QUAD))
  465.     {
  466.         mel = (FL_SWIM * mel);
  467.     }
  468.     if ((dist > mel))
  469.     {
  470.         return (FALSE);
  471.     }
  472.     dist = vlen ((self.origin - spot2));
  473.     mel = ((280 - (self.health * 0.5)) - (self.armorvalue * self.armortype));
  474.     if ((self.items & IT_QUAD))
  475.     {
  476.         mel = (FL_SWIM * mel);
  477.     }
  478.     if ((dist < mel))
  479.     {
  480.         return (FALSE);
  481.     }
  482.     REBOUNDSPOT = spot2;
  483.     REBOUND = TRUE;
  484.     self.ideal_yaw = vectoyaw ((spot2 - self.origin));
  485.     ChangeYaw ();
  486.     bot_rebound1 ();
  487.     if ((self.items & IT_ROCKET_LAUNCHER))
  488.     {
  489.         W_FireRocket ();
  490.     }
  491.     else
  492.     {
  493.         REBOUNDSPOT = (spot2 + (random () * '12 12 12'));
  494.         W_FireGrenade ();
  495.     }
  496.     self.attack_finished = (time + TRUE);
  497.     if ((self.skil < FL_SWIM))
  498.     {
  499.         self.attack_finished = (time + 1.5);
  500.     }
  501.     REBOUND = FALSE;
  502. };
  503.  
  504.  
  505.  
  506. void (entity e) clearCache;
  507.  
  508. float () CheckWaterLevel =
  509. {
  510.     local float pnt;
  511.  
  512.     if ((self.waterlevel < TRUE))
  513.     {
  514.         return (FALSE);
  515.     }
  516.     pnt = pointcontents ((self.origin + self.view_ofs));
  517.     if ((pnt != CONTENT_EMPTY))
  518.     {
  519.         return (MOVETYPE_WALK);
  520.     }
  521.     pnt = pointcontents (self.origin);
  522.     if ((pnt != CONTENT_EMPTY))
  523.     {
  524.         return (FL_SWIM);
  525.     }
  526.     return (TRUE);
  527. };
  528.  
  529. void () BotWaterMove =
  530. {
  531.     local float wlevel;
  532.     local float wtype;
  533.     local float pnt;
  534.     local vector bt;
  535.  
  536.     wlevel = CheckWaterLevel ();
  537.     if ((self.health < FALSE))
  538.     {
  539.         return;
  540.     }
  541.     if ((wlevel != MOVETYPE_WALK))
  542.     {
  543.         if ((self.air_finished < time))
  544.         {
  545.             sound (self, CHAN_VOICE, "player/gasp2.wav", TRUE, ATTN_NORM);
  546.         }
  547.         else
  548.         {
  549.             if ((self.air_finished < (time + MOVETYPE_FLYMISSILE)))
  550.             {
  551.                 sound (self, CHAN_VOICE, "player/gasp1.wav", TRUE, ATTN_NORM);
  552.             }
  553.         }
  554.         self.air_finished = (time + KINDA_WANT);
  555.         self.dmg = FL_SWIM;
  556.     }
  557.     else
  558.     {
  559.         if ((self.air_finished < time))
  560.         {
  561.             if ((self.pain_finished < time))
  562.             {
  563.                 self.dmg = (self.dmg + FL_SWIM);
  564.                 if ((self.dmg > 15))
  565.                 {
  566.                     self.dmg = MOVETYPE_BOUNCE;
  567.                 }
  568.                 T_Damage (self, world, world, self.dmg);
  569.                 self.pain_finished = (time + TRUE);
  570.             }
  571.         }
  572.     }
  573.     wtype = self.watertype;
  574.     if ((wlevel < TRUE))
  575.     {
  576.         bt = ((self.absmin + self.absmax) * 0.5);
  577.         bt_z = (self.absmin_z + TRUE);
  578.         pnt = pointcontents (bt);
  579.         if ((pnt != CONTENT_EMPTY))
  580.         {
  581.             wlevel = TRUE;
  582.             wtype = pnt;
  583.         }
  584.     }
  585.     if ((self.waterlevel < TRUE))
  586.     {
  587.         if ((self.flags & FL_INWATER))
  588.         {
  589.             sound (self, CHAN_BODY, "misc/outwater.wav", TRUE, ATTN_NORM);
  590.             self.flags = (self.flags - FL_INWATER);
  591.         }
  592.         if ((self.flags & FL_SWIM))
  593.         {
  594.             self.flags = (self.flags - FL_SWIM);
  595.         }
  596.         if ((wlevel < TRUE))
  597.         {
  598.             return;
  599.         }
  600.     }
  601.     if ((wtype == CONTENT_LAVA))
  602.     {
  603.         if ((self.dmgtime < time))
  604.         {
  605.             if ((self.radsuit_finished > time))
  606.             {
  607.                 self.dmgtime = (time + TRUE);
  608.             }
  609.             else
  610.             {
  611.                 self.dmgtime = (time + 0.2);
  612.             }
  613.             T_Damage (self, world, world, (MOVETYPE_BOUNCE * wlevel));
  614.         }
  615.     }
  616.     else
  617.     {
  618.         if ((wtype == CONTENT_SLIME))
  619.         {
  620.             if (((self.dmgtime < time) && (self.radsuit_finished < time)))
  621.             {
  622.                 self.dmgtime = (time + TRUE);
  623.                 T_Damage (self, world, world, (MOVETYPE_STEP * wlevel));
  624.             }
  625.         }
  626.     }
  627.     if ((self.waterlevel < TRUE))
  628.     {
  629.         return;
  630.     }
  631.     if (!(self.flags & FL_INWATER))
  632.     {
  633.         if ((self.watertype == CONTENT_LAVA))
  634.         {
  635.             sound (self, CHAN_BODY, "player/inlava.wav", TRUE, ATTN_NORM);
  636.         }
  637.         if ((self.watertype == CONTENT_WATER))
  638.         {
  639.             sound (self, CHAN_BODY, "player/inh2o.wav", TRUE, ATTN_NORM);
  640.         }
  641.         if ((self.watertype == CONTENT_SLIME))
  642.         {
  643.             sound (self, CHAN_BODY, "player/slimbrn2.wav", TRUE, ATTN_NORM);
  644.         }
  645.         self.flags = (self.flags + FL_INWATER);
  646.         if (!(self.flags & FL_SWIM))
  647.         {
  648.             self.flags = (self.flags + FL_SWIM);
  649.         }
  650.         self.dmgtime = FALSE;
  651.     }
  652. };
  653.  
  654. void () BotCheckPowerups =
  655. {
  656.     if ((self.health <= FALSE))
  657.     {
  658.         return;
  659.     }
  660.     if (self.invisible_finished)
  661.     {
  662.         if ((self.invisible_sound < time))
  663.         {
  664.             sound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
  665.             self.invisible_sound = (time + ((random () * MOVETYPE_WALK) + TRUE));
  666.         }
  667.         if ((self.invisible_finished < (time + MOVETYPE_WALK)))
  668.         {
  669.             if ((self.invisible_time == TRUE))
  670.             {
  671.                 sound (self, CHAN_AUTO, "items/inv2.wav", TRUE, ATTN_NORM);
  672.                 self.invisible_time = (time + TRUE);
  673.             }
  674.             if ((self.invisible_time < time))
  675.             {
  676.                 self.invisible_time = (time + TRUE);
  677.             }
  678.         }
  679.         if ((self.invisible_finished < time))
  680.         {
  681.             self.items = (self.items - IT_INVISIBILITY);
  682.             self.invisible_finished = FALSE;
  683.             self.invisible_time = FALSE;
  684.         }
  685.         self.frame = FALSE;
  686.         self.modelindex = modelindex_eyes;
  687.     }
  688.     else
  689.     {
  690.         self.modelindex = modelindex_player;
  691.     }
  692.     if (self.invincible_finished)
  693.     {
  694.         if ((self.invincible_finished < (time + MOVETYPE_WALK)))
  695.         {
  696.             if ((self.invincible_time == TRUE))
  697.             {
  698.                 sound (self, CHAN_AUTO, "items/protect2.wav", TRUE, ATTN_NORM);
  699.                 self.invincible_time = (time + TRUE);
  700.             }
  701.             if ((self.invincible_time < time))
  702.             {
  703.                 self.invincible_time = (time + TRUE);
  704.             }
  705.         }
  706.         if ((self.invincible_finished < time))
  707.         {
  708.             self.items = (self.items - IT_INVULNERABILITY);
  709.             self.invincible_time = FALSE;
  710.             self.invincible_finished = FALSE;
  711.         }
  712.         if ((self.invincible_finished > time))
  713.         {
  714.             self.effects = (self.effects | EF_DIMLIGHT);
  715.         }
  716.         else
  717.         {
  718.             self.effects = (self.effects - (self.effects & EF_DIMLIGHT));
  719.         }
  720.     }
  721.     if (self.super_damage_finished)
  722.     {
  723.         if ((self.super_damage_finished < (time + MOVETYPE_WALK)))
  724.         {
  725.             if ((self.super_time == TRUE))
  726.             {
  727.                 sound (self, CHAN_AUTO, "items/damage2.wav", TRUE, ATTN_NORM);
  728.                 self.super_time = (time + TRUE);
  729.             }
  730.             if ((self.super_time < time))
  731.             {
  732.                 self.super_time = (time + TRUE);
  733.             }
  734.         }
  735.         if ((self.super_damage_finished < time))
  736.         {
  737.             self.items = (self.items - IT_QUAD);
  738.             self.super_damage_finished = FALSE;
  739.             self.super_time = FALSE;
  740.         }
  741.         if ((self.super_damage_finished > time))
  742.         {
  743.             self.effects = (self.effects | EF_DIMLIGHT);
  744.         }
  745.         else
  746.         {
  747.             self.effects = (self.effects - (self.effects & EF_DIMLIGHT));
  748.         }
  749.     }
  750.     if (self.radsuit_finished)
  751.     {
  752.         self.air_finished = (time + 12);
  753.         if ((self.radsuit_finished < (time + MOVETYPE_WALK)))
  754.         {
  755.             if ((self.rad_time == TRUE))
  756.             {
  757.                 sound (self, CHAN_AUTO, "items/suit2.wav", TRUE, ATTN_NORM);
  758.                 self.rad_time = (time + TRUE);
  759.             }
  760.             if ((self.rad_time < time))
  761.             {
  762.                 self.rad_time = (time + TRUE);
  763.             }
  764.         }
  765.         if ((self.radsuit_finished < time))
  766.         {
  767.             self.items = (self.items - IT_SUIT);
  768.             self.rad_time = FALSE;
  769.             self.radsuit_finished = FALSE;
  770.         }
  771.     }
  772. };
  773. void () BotDead;
  774.  
  775. void () BotPostThink =
  776. {
  777.     local float fraglimit;
  778.  
  779.     if (self.pather)
  780.     {
  781.         if (CheckDropPath ())
  782.         {
  783.             DropBotPath ();
  784.         }
  785.     }
  786.     self.movetarget.flags = self.flags;
  787.     setorigin (self.movetarget, self.origin);
  788.     if ((self.deadflag != DEAD_NO))
  789.     {
  790.         dprint ("Bot should be dead!\n");
  791.         GibPlayer ();
  792.         BotDead ();
  793.         return;
  794.     }
  795.     BotCheckPowerups ();
  796.     BotWaterMove ();
  797.     fraglimit = cvar ("fraglimit");
  798.     if ((fraglimit && (self.frags >= fraglimit)))
  799.     {
  800.         NextLevel ();
  801.         self.button0 = TRUE;
  802.         self.think = IntermissionThink;
  803.         self.nextthink = (time + MOVETYPE_FLY);
  804.         return;
  805.     }
  806. };
  807.  
  808.  
  809. void () AddAnotherBot;
  810.  
  811. void () initBotLevel =
  812. {
  813.     local float num;
  814.     local float offset;
  815.     local float i;
  816.     local entity e;
  817.     local string tmp;
  818.  
  819.     NOISEQUEUE = noisetarget ();
  820.     num = ((serverflags & BOTS) / FL_INWATER);
  821.     serverflags = ((serverflags - (serverflags & BOTS)) - INITLEVEL);
  822.     NUMBOTS = FALSE;
  823.     NUMPATHS = FALSE;
  824.     NUMPATHERS = FALSE;
  825.     offset = TRUE;
  826.     while ((num > FALSE))
  827.     {
  828.         num = (num - TRUE);
  829.         if (((NUMBOTS < MOVETYPE_FLY) && !(serverflags & DEDICATED)))
  830.         {
  831.             skill = ((0.1 * (parm10 & (offset * SVC_FINALE))) / offset);
  832.         }
  833.         offset = (offset * FL_MONSTER);
  834.         AddAnotherBot ();
  835.     }
  836.     if ((serverflags & TEAMFLAG))
  837.     {
  838.         if (!teamplay)
  839.         {
  840.             serverflags = (serverflags - TEAMFLAG);
  841.             serverflags = (serverflags - (serverflags & TEAMBOTS));
  842.             return;
  843.         }
  844.     }
  845.     else
  846.     {
  847.         if (teamplay)
  848.         {
  849.             serverflags = (serverflags + TEAMFLAG);
  850.             serverflags = (serverflags - (serverflags & TEAMBOTS));
  851.             return;
  852.         }
  853.     }
  854.     if (!teamplay)
  855.     {
  856.         return;
  857.     }
  858.     num = ((serverflags & TEAMBOTS) / FL_ITEM);
  859.     if ((num == FALSE))
  860.     {
  861.         return;
  862.     }
  863.     e = find (world, classname, "player");
  864.     while (e)
  865.     {
  866.         i = FALSE;
  867.         offset = TRUE;
  868.         while ((i < num))
  869.         {
  870.             i = (i + TRUE);
  871.             if (((i < MOVETYPE_TOSS) && !(serverflags & DEDICATED)))
  872.             {
  873.                 skill = ((0.1 * (parm11 & (offset * SVC_FINALE))) / offset);
  874.             }
  875.             offset = (offset * FL_MONSTER);
  876.             addTeamBots (e, TRUE);
  877.         }
  878.         e = find (e, classname, "player");
  879.     }
  880.     if ((serverflags & DEDICATED))
  881.     {
  882.         serverflags = (serverflags - DEDICATED);
  883.     }
  884. };
  885.  
  886. void () setBotGravity =
  887. {
  888.     local float newmax;
  889.     local float vel;
  890.     local float sk;
  891.     local string tmp;
  892.  
  893.     GRAVITY = (cvar ("sv_gravity") * 0.1);
  894.     dprint ("Gravity accel is ");
  895.     tmp = ftos (GRAVITY);
  896.     dprint (tmp);
  897.     dprint ("\n");
  898.     newmax = FALSE;
  899.     vel = 270;
  900.     MAXJUMP = CONTENT_EMPTY;
  901.     while ((newmax > MAXJUMP))
  902.     {
  903.         vel = (vel - GRAVITY);
  904.         MAXJUMP = newmax;
  905.         newmax = (newmax + (vel * 0.1));
  906.     }
  907.     MAXJUMP = (MAXJUMP - TRUE);
  908.     dprint ("Max jump height is ");
  909.     tmp = ftos (MAXJUMP);
  910.     dprint (tmp);
  911.     dprint ("\n");
  912.     LEVELJUMPTIME = FALSE;
  913.     vel = 270;
  914.     newmax = FALSE;
  915.     while ((newmax > CONTENT_EMPTY))
  916.     {
  917.         LEVELJUMPTIME = (LEVELJUMPTIME + 0.1);
  918.         vel = (vel - GRAVITY);
  919.         newmax = (newmax + (vel * 0.1));
  920.     }
  921.     LEVELJUMPTIME = (LEVELJUMPTIME - (newmax / vel));
  922.     dprint ("Level jump time is ");
  923.     tmp = ftos (LEVELJUMPTIME);
  924.     dprint (tmp);
  925.     dprint ("\n");
  926.     newmax = FALSE;
  927.     vel = 200;
  928.     GRENADEMAXHEIGHT = CONTENT_EMPTY;
  929.     while ((newmax > GRENADEMAXHEIGHT))
  930.     {
  931.         vel = (vel - GRAVITY);
  932.         GRENADEMAXHEIGHT = newmax;
  933.         newmax = (newmax + (vel * 0.1));
  934.     }
  935.     dprint ("Max grenade height is ");
  936.     tmp = ftos (GRENADEMAXHEIGHT);
  937.     dprint (tmp);
  938.     dprint ("\n");
  939.     INVGRENADELEVELDIST = (((0.1 * FL_SWIM) * (200 - GRAVITY)) / GRAVITY);
  940.     INVGRENADELEVELDIST = (TRUE / (INVGRENADELEVELDIST * SEARCH_RADIUS));
  941.     dprint ("inverse grenade level distance is ");
  942.     tmp = ftos (INVGRENADELEVELDIST);
  943.     dprint (tmp);
  944.     dprint ("\n");
  945.     BOTSPEED = (cvar ("sv_maxspeed") / MOVETYPE_BOUNCE);
  946. };
  947. void () PutBotInServer;
  948. float () numplayers;
  949. float (entity e) totalscore;
  950.  
  951. void () respawnBot =
  952. {
  953.     local string m;
  954.     local float n;
  955.     local float o;
  956.     local entity e;
  957.  
  958.     CopyToBodyQue (self);
  959.     if (!teamplay)
  960.     {
  961.         if ((serverflags & TEAMBOTS))
  962.         {
  963.             n = (NUMBOTS + numplayers ());
  964.             o = ((serverflags & TEAMBOTS) / FL_ITEM);
  965.             if (((o < n) || (self.team != 99)))
  966.             {
  967.                 self.nextthink = (time + TRUE);
  968.                 if ((self.team == 99))
  969.                 {
  970.                     NUMBOTS = (NUMBOTS - TRUE);
  971.                 }
  972.                 remove (self.movetarget);
  973.                 remove (self.goalentity);
  974.                 self.think = SUB_Remove;
  975.                 if (self.pather)
  976.                 {
  977.                     NUMPATHERS = (NUMPATHERS - TRUE);
  978.                 }
  979.                 if ((self.team != 99))
  980.                 {
  981.                     m = ": I'm going to find a team server.\n";
  982.                 }
  983.                 else
  984.                 {
  985.                     if ((totalscore (self) < FALSE))
  986.                     {
  987.                         m = ": I'm tired of getting fragged.  I'm off\n";
  988.                     }
  989.                     else
  990.                     {
  991.                         if ((totalscore (self) > MUST_HAVE))
  992.                         {
  993.                             m = ": I'm going to find some real competition\n";
  994.                         }
  995.                         else
  996.                         {
  997.                             m = ": This server's too crowded.  I'm off\n";
  998.                         }
  999.                     }
  1000.                 }
  1001.                 bprint (self.teamname);
  1002.                 bprint (self.netname);
  1003.                 bprint (m);
  1004.                 bprint (self.teamname);
  1005.                 bprint (self.netname);
  1006.                 bprint (" left the game with ");
  1007.                 m = ftos (self.frags);
  1008.                 bprint (m);
  1009.                 bprint (" frags\n");
  1010.                 return;
  1011.             }
  1012.         }
  1013.     }
  1014.     else
  1015.     {
  1016.         if ((self.team != 99))
  1017.         {
  1018.             e = find (world, classname, "player");
  1019.             while (e)
  1020.             {
  1021.                 if ((e.team == self.team))
  1022.                 {
  1023.                     PutBotInServer ();
  1024.                     return;
  1025.                 }
  1026.                 e = find (e, classname, "player");
  1027.             }
  1028.             bprint (self.teamname);
  1029.             bprint (self.netname);
  1030.             bprint (": Going off to join my team\n");
  1031.             bprint (self.teamname);
  1032.             bprint (self.netname);
  1033.             bprint (" left the game with ");
  1034.             m = ftos (self.frags);
  1035.             bprint (m);
  1036.             bprint (" frags\n");
  1037.             return;
  1038.         }
  1039.         else
  1040.         {
  1041.             if ((SKINSMODE == FL_SWIM))
  1042.             {
  1043.                 skinChange (self, 15);
  1044.             }
  1045.         }
  1046.     }
  1047.     PutBotInServer ();
  1048. };
  1049. void () bot_pain;
  1050. void () BotDie;
  1051. void () bot_stand1;
  1052. void () bot_walk;
  1053. void () bot_run;
  1054. void () bot_start;
  1055. void () dmbot_melee;
  1056. entity () botmovetarget;
  1057.  
  1058. void () PutBotInServer =
  1059. {
  1060.     local entity spwn;
  1061.     local vector spot;
  1062.     local string tmp;
  1063.     local float aimvar;
  1064.  
  1065.     self.classname = "dmbot";
  1066.     self.health = MUST_HAVE;
  1067.     self.takedamage = DAMAGE_AIM;
  1068.     self.solid = SOLID_SLIDEBOX;
  1069.     self.movetype = MOVETYPE_STEP;
  1070.     self.show_hostile = FALSE;
  1071.     self.max_health = MUST_HAVE;
  1072.     self.air_finished = (time + SVC_INTERMISSION);
  1073.     self.dmg = TRUE;
  1074.     self.super_damage_finished = FALSE;
  1075.     self.radsuit_finished = FALSE;
  1076.     self.invisible_finished = FALSE;
  1077.     self.invincible_finished = FALSE;
  1078.     self.effects = FALSE;
  1079.     self.invincible_time = FALSE;
  1080.     self.yaw_speed = (45 + (25 * self.skil));
  1081.     self.lefty = STRAFE_DIR;
  1082.     if ((self.goalentity == world))
  1083.     {
  1084.         self.goalentity = botmovetarget ();
  1085.     }
  1086.     self.goalentity.goalentity = world;
  1087.     SetNewParms ();
  1088.     DecodeLevelParms ();
  1089.     W_SetCurrentAmmo ();
  1090.     self.search_time = time;
  1091.     self.attack_finished = time;
  1092.     self.th_pain = bot_pain;
  1093.     self.th_die = BotDie;
  1094.     self.th_stand = bot_stand1;
  1095.     self.th_walk = bot_walk;
  1096.     self.th_run = bot_run;
  1097.     self.th_melee = dmbot_melee;
  1098.     self.th_cache = cacheenemy;
  1099.     self.think = bot_start;
  1100.     self.nextthink = (time + 0.1);
  1101.     self.enemy = world;
  1102.     self.pathtype = NEVERTARGET;
  1103.     self.deadflag = DEAD_NO;
  1104.     self.pausetime = FALSE;
  1105.     spwn = SelectSpawnPoint ();
  1106.     spot = (spwn.origin + '0 0 1');
  1107.     self.origin = spot;
  1108.     setorigin (self, spot);
  1109.     self.angles = spwn.angles;
  1110.     self.fixangle = TRUE;
  1111.     setmodel (self, "progs/eyes.mdl");
  1112.     modelindex_eyes = self.modelindex;
  1113.     setmodel (self, "progs/player.mdl");
  1114.     modelindex_player = self.modelindex;
  1115.     setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
  1116.     if ((self.movetarget == world))
  1117.     {
  1118.         NewCarriedPath ();
  1119.     }
  1120.     else
  1121.     {
  1122.         setorigin (self.movetarget, self.origin);
  1123.     }
  1124.     self.movetarget.movetarget = world;
  1125.     clearCache (self);
  1126.     if (self.pather)
  1127.     {
  1128.         NUMPATHERS = (NUMPATHERS - TRUE);
  1129.         self.pather = FALSE;
  1130.     }
  1131.     if ((NUMPATHERS < MAXPATHERS))
  1132.     {
  1133.         self.pather = TRUE;
  1134.         NUMPATHERS = (NUMPATHERS + TRUE);
  1135.     }
  1136.     self.view_ofs = '0 0 22';
  1137.     makevectors (self.angles);
  1138.     spawn_tfog ((self.origin + (v_forward * KINDA_WANT)));
  1139.     spawn_tdeath (self.origin, self);
  1140.     if ((BOTSPEED < FL_MONSTER))
  1141.     {
  1142.         dprint ("Feeling kind of slow today (SV_MAXSPEED = ");
  1143.         tmp = ftos ((BOTSPEED * MOVETYPE_BOUNCE));
  1144.         dprint (tmp);
  1145.         dprint ("\n");
  1146.     }
  1147.     aimvar = cvar ("sv_aim");
  1148.     if ((aimvar != 0.93))
  1149.     {
  1150.         dprint ("Seems like sv_aim isn't 0.93\n");
  1151.     }
  1152. };
  1153.  
  1154. void () SpawnNewBot =
  1155. {
  1156.     local string tmp;
  1157.  
  1158.     PutBotInServer ();
  1159.     bprint (self.teamname);
  1160.     bprint (self.netname);
  1161.     tmp = ftos (self.skil);
  1162.     bprint (" (skill ");
  1163.     bprint (tmp);
  1164.     bprint (") entered the game.\n");
  1165. };
  1166.  
  1167. entity () AddBot =
  1168. {
  1169.     local entity newbot;
  1170.     local entity oldself;
  1171.     local string mycolor;
  1172.     local float plycolor;
  1173.  
  1174.     newbot = spawn ();
  1175.     oldself = self;
  1176.     self = newbot;
  1177.     self.think = SpawnNewBot;
  1178.     self.nextthink = (time + (12 * random ()));
  1179.     self.skil = skill;
  1180.     if ((self.skil < FALSE))
  1181.     {
  1182.         self.skil = FALSE;
  1183.     }
  1184.     else
  1185.     {
  1186.         if ((self.skil > MOVETYPE_WALK))
  1187.         {
  1188.             self.skil = MOVETYPE_WALK;
  1189.         }
  1190.     }
  1191.     initscore ();
  1192.     self = oldself;
  1193.     return (newbot);
  1194. };
  1195.  
  1196. float () numplayers =
  1197. {
  1198.     local entity e;
  1199.     local float n;
  1200.  
  1201.     n = FALSE;
  1202.     e = find (world, classname, "player");
  1203.     while (e)
  1204.     {
  1205.         n = (n + TRUE);
  1206.         e = find (e, classname, "player");
  1207.     }
  1208.     return (n);
  1209. };
  1210.  
  1211. void () AddAnotherBot =
  1212. {
  1213.     local entity newbot;
  1214.     local entity tmp;
  1215.     local float n;
  1216.     local string st;
  1217.  
  1218.     self.impulse = FALSE;
  1219.     if (!teamplay)
  1220.     {
  1221.         if ((serverflags & TEAMBOTS))
  1222.         {
  1223.             n = (NUMBOTS + numplayers ());
  1224.             if (((serverflags & TEAMBOTS) < n))
  1225.             {
  1226.                 dprint ("Can't add bot - exceeds bound\n");
  1227.                 return;
  1228.             }
  1229.         }
  1230.     }
  1231.     newbot = AddBot ();
  1232.     newbot.colormap = FALSE;
  1233.     if (teamplay)
  1234.     {
  1235.         skinChange (newbot, 15);
  1236.     }
  1237.     else
  1238.     {
  1239.         if ((SKINSMODE == TRUE))
  1240.         {
  1241.             skinChange (newbot, NUMBOTS);
  1242.         }
  1243.         else
  1244.         {
  1245.             if ((SKINSMODE == FL_SWIM))
  1246.             {
  1247.                 st = ftos (((newbot.skil & MOVETYPE_WALK) + TRUE));
  1248.                 dprint (st);
  1249.                 dprint ("= skil skin\n");
  1250.                 skinChange (newbot, ((newbot.skil & MOVETYPE_WALK) + TRUE));
  1251.             }
  1252.         }
  1253.     }
  1254.     newbot.team = 99;
  1255.     if (NAMEBOTS)
  1256.     {
  1257.         newbot.teamname = self.netname;
  1258.     }
  1259.     else
  1260.     {
  1261.         if ((newbot.skil < TRUE))
  1262.         {
  1263.             newbot.teamname = "Reaper0Bot";
  1264.         }
  1265.         else
  1266.         {
  1267.             if ((newbot.skil < FL_SWIM))
  1268.             {
  1269.                 newbot.teamname = "Reaper1Bot";
  1270.             }
  1271.             else
  1272.             {
  1273.                 if ((newbot.skil < MOVETYPE_WALK))
  1274.                 {
  1275.                     newbot.teamname = "Reaper2Bot";
  1276.                 }
  1277.                 else
  1278.                 {
  1279.                     newbot.teamname = "Reaper3Bot";
  1280.                 }
  1281.             }
  1282.         }
  1283.     }
  1284.     NUMBOTS = (NUMBOTS + TRUE);
  1285.     if ((NUMBOTS == TRUE))
  1286.     {
  1287.         newbot.nextthink = (time + 0.1);
  1288.     }
  1289.     if ((NUMBOTS < FL_INWATER))
  1290.     {
  1291.         serverflags = ((serverflags - (serverflags & BOTS)) + (FL_INWATER * NUMBOTS));
  1292.     }
  1293.     if ((NUMBOTS == TRUE))
  1294.     {
  1295.         newbot.netname = "1";
  1296.     }
  1297.     else
  1298.     {
  1299.         if ((NUMBOTS == FL_SWIM))
  1300.         {
  1301.             newbot.netname = "2";
  1302.         }
  1303.         else
  1304.         {
  1305.             if ((NUMBOTS == MOVETYPE_WALK))
  1306.             {
  1307.                 newbot.netname = "3";
  1308.             }
  1309.             else
  1310.             {
  1311.                 if ((NUMBOTS == MOVETYPE_STEP))
  1312.                 {
  1313.                     newbot.netname = "4";
  1314.                 }
  1315.                 else
  1316.                 {
  1317.                     if ((NUMBOTS == MOVETYPE_FLY))
  1318.                     {
  1319.                         newbot.netname = "5";
  1320.                     }
  1321.                     else
  1322.                     {
  1323.                         if ((NUMBOTS == MOVETYPE_TOSS))
  1324.                         {
  1325.                             newbot.netname = "6";
  1326.                         }
  1327.                         else
  1328.                         {
  1329.                             if ((NUMBOTS == MOVETYPE_PUSH))
  1330.                             {
  1331.                                 newbot.netname = "7";
  1332.                             }
  1333.                             else
  1334.                             {
  1335.                                 if ((NUMBOTS == FL_CLIENT))
  1336.                                 {
  1337.                                     newbot.netname = "8";
  1338.                                 }
  1339.                                 else
  1340.                                 {
  1341.                                     if ((NUMBOTS == MOVETYPE_FLYMISSILE))
  1342.                                     {
  1343.                                         newbot.netname = "9";
  1344.                                     }
  1345.                                     else
  1346.                                     {
  1347.                                         if ((NUMBOTS == MOVETYPE_BOUNCE))
  1348.                                         {
  1349.                                             newbot.netname = "10";
  1350.                                         }
  1351.                                         else
  1352.                                         {
  1353.                                             if ((NUMBOTS == MOVETYPE_BOUNCEMISSILE))
  1354.                                             {
  1355.                                                 newbot.netname = "11";
  1356.                                             }
  1357.                                             else
  1358.                                             {
  1359.                                                 if ((NUMBOTS == 12))
  1360.                                                 {
  1361.                                                     newbot.netname = "12";
  1362.                                                 }
  1363.                                                 else
  1364.                                                 {
  1365.                                                     if ((NUMBOTS == 13))
  1366.                                                     {
  1367.                                                         newbot.netname = "13";
  1368.                                                     }
  1369.                                                     else
  1370.                                                     {
  1371.                                                         if ((NUMBOTS == 14))
  1372.                                                         {
  1373.                                                             newbot.netname = "14";
  1374.                                                         }
  1375.                                                         else
  1376.                                                         {
  1377.                                                             if ((NUMBOTS == 15))
  1378.                                                             {
  1379.                                                                 newbot.netname = "15";
  1380.                                                             }
  1381.                                                         }
  1382.                                                     }
  1383.                                                 }
  1384.                                             }
  1385.                                         }
  1386.                                     }
  1387.                                 }
  1388.                             }
  1389.                         }
  1390.                     }
  1391.                 }
  1392.             }
  1393.         }
  1394.     }
  1395. };
  1396.  
  1397. void (entity ply, float n) addTeamBots =
  1398. {
  1399.     local entity newbot;
  1400.     local entity tmp;
  1401.     local float i;
  1402.  
  1403.     i = n;
  1404.     while ((i > FALSE))
  1405.     {
  1406.         newbot = AddBot ();
  1407.         newbot.colormap = ply.colormap;
  1408.         newbot.team = ply.team;
  1409.         newbot.teamname = ply.netname;
  1410.         skinChange (newbot, ply.skin);
  1411.         if ((newbot.skil < TRUE))
  1412.         {
  1413.             newbot.netname = "0Bot";
  1414.         }
  1415.         else
  1416.         {
  1417.             if ((newbot.skil < FL_SWIM))
  1418.             {
  1419.                 newbot.netname = "1Bot";
  1420.             }
  1421.             else
  1422.             {
  1423.                 if ((newbot.skil < MOVETYPE_WALK))
  1424.                 {
  1425.                     newbot.netname = "2Bot";
  1426.                 }
  1427.                 else
  1428.                 {
  1429.                     newbot.netname = "3Bot";
  1430.                 }
  1431.             }
  1432.         }
  1433.         i = (i - TRUE);
  1434.     }
  1435. };
  1436.  
  1437. void (entity ply, float n) removeTeamBots =
  1438. {
  1439.     local float i;
  1440.     local entity e;
  1441.  
  1442.     i = n;
  1443.     e = find (world, classname, "dmbot");
  1444.     while ((i > FALSE))
  1445.     {
  1446.         while (((e != world) && (e.team != ply.team)))
  1447.         {
  1448.             e = find (e, classname, "dmbot");
  1449.         }
  1450.         if (!e)
  1451.         {
  1452.             return;
  1453.         }
  1454.         if (e.pather)
  1455.         {
  1456.             NUMPATHERS = (NUMPATHERS - TRUE);
  1457.         }
  1458.         remove (e.movetarget);
  1459.         remove (e.goalentity);
  1460.         remove (e);
  1461.         i = (i - TRUE);
  1462.     }
  1463. };
  1464.  
  1465. void () removeAllBots =
  1466. {
  1467.     local entity e;
  1468.  
  1469.     e = find (world, classname, "dmbot");
  1470.     while (e)
  1471.     {
  1472.         if (!e)
  1473.         {
  1474.             return;
  1475.         }
  1476.         if (e.pather)
  1477.         {
  1478.             NUMPATHERS = (NUMPATHERS - TRUE);
  1479.         }
  1480.         remove (e.movetarget);
  1481.         remove (e.goalentity);
  1482.         remove (e);
  1483.         e = find (e, classname, "dmbot");
  1484.     }
  1485.     NUMBOTS = FALSE;
  1486.     dprint ("All bots removed.\n");
  1487. };
  1488.  
  1489. void (float n) SetMaxBots =
  1490. {
  1491.     local float t;
  1492.     local string tmp;
  1493.  
  1494.     self.impulse = FALSE;
  1495.     if ((serverflags & TEAMFLAG))
  1496.     {
  1497.         dprint ("Entering bounded deathmatch mode\n");
  1498.         serverflags = ((serverflags - TEAMFLAG) - (serverflags & TEAMBOTS));
  1499.     }
  1500.     dprint ("Max bots + players set to ");
  1501.     tmp = ftos (n);
  1502.     dprint (tmp);
  1503.     dprint ("\n");
  1504.     serverflags = ((serverflags - (serverflags & TEAMBOTS)) + (n * FL_ITEM));
  1505.     t = numplayers ();
  1506.     while (((NUMBOTS + t) < n))
  1507.     {
  1508.         AddAnotherBot ();
  1509.     }
  1510. };
  1511.  
  1512. void (float n) SetTeamBots =
  1513. {
  1514.     local float t;
  1515.     local entity e;
  1516.     local string tmp;
  1517.  
  1518.     self.impulse = FALSE;
  1519.     if (!(serverflags & TEAMFLAG))
  1520.     {
  1521.         dprint ("Entering bot team mode\n");
  1522.         serverflags = ((serverflags + TEAMFLAG) - (serverflags & TEAMBOTS));
  1523.     }
  1524.     dprint ("Bots per player team set to ");
  1525.     tmp = ftos (n);
  1526.     dprint (tmp);
  1527.     dprint ("\n");
  1528.     t = ((serverflags & TEAMBOTS) / FL_ITEM);
  1529.     serverflags = ((serverflags - (serverflags & TEAMBOTS)) + (n * FL_ITEM));
  1530.     if ((t < n))
  1531.     {
  1532.         e = find (world, classname, "player");
  1533.         t = (n - t);
  1534.         while (e)
  1535.         {
  1536.             addTeamBots (e, t);
  1537.             e = find (e, classname, "player");
  1538.         }
  1539.         return;
  1540.     }
  1541.     if ((t > n))
  1542.     {
  1543.         e = find (world, classname, "player");
  1544.         while (e)
  1545.         {
  1546.             t = (t - n);
  1547.             removeTeamBots (e, t);
  1548.             e = find (e, classname, "player");
  1549.         }
  1550.         return;
  1551.     }
  1552. };
  1553.  
  1554. void () UpdateTeamColors =
  1555. {
  1556.     local entity e;
  1557.  
  1558.     e = find (world, classname, "dmbot");
  1559.     while (e)
  1560.     {
  1561.         if ((e.colormap == self.colormap))
  1562.         {
  1563.             e.team = self.team;
  1564.         }
  1565.         e = find (e, classname, "dmbot");
  1566.     }
  1567. };
  1568.  
  1569.  
  1570. void () t_botmovetarget;
  1571. entity (entity chaser, entity en) BestChaseRoute;
  1572.  
  1573. entity () botmovetarget =
  1574. {
  1575.     local entity targ;
  1576.  
  1577.     targ = spawn ();
  1578.     targ.classname = "BotTarget";
  1579.     targ.solid = SOLID_TRIGGER;
  1580.     targ.movetarget = world;
  1581.     targ.touch = t_botmovetarget;
  1582.     setsize (targ, '-4 -4 0', '4 4 8');
  1583.     return (targ);
  1584. };
  1585.  
  1586. void () t_botmovetarget =
  1587. {
  1588.     local vector in;
  1589.     local entity tmp;
  1590.     local entity pth;
  1591.     local float rnd;
  1592.  
  1593.     if ((other.goalentity != self))
  1594.     {
  1595.         return;
  1596.     }
  1597.     if ((self.classname != "BotTarget"))
  1598.     {
  1599.         objerror ("bad bot target in bot_touch! 1\n");
  1600.     }
  1601.     if ((self.goalentity.classname != "player"))
  1602.     {
  1603.         if (VERBOSEBOT)
  1604.         {
  1605.             dprint (other.teamname);
  1606.             dprint (other.netname);
  1607.             dprint (" got to ");
  1608.             dprint (self.goalentity.classname);
  1609.             dprint ("\n");
  1610.         }
  1611.         other.lefty = (other.lefty - (other.lefty & LOCAL_TIME));
  1612.         if ((self.goalentity.classname == "door"))
  1613.         {
  1614.             if ((self.goalentity.use == fd_secret_use))
  1615.             {
  1616.                 return;
  1617.             }
  1618.         }
  1619.         if ((self.goalentity.classname == "train"))
  1620.         {
  1621.             if (!(other.lefty & ONTRAIN))
  1622.             {
  1623.                 other.lefty = (other.lefty | ONTRAIN);
  1624.                 other.search_time = (time + TRUE);
  1625.             }
  1626.             return;
  1627.         }
  1628.         if ((self.goalentity.classname != "func_button"))
  1629.         {
  1630.             if ((other.lefty & GETGOODY))
  1631.             {
  1632.                 other.goody_time = time;
  1633.             }
  1634.             else
  1635.             {
  1636.                 other.search_time = time;
  1637.             }
  1638.             return;
  1639.         }
  1640.         tmp = self;
  1641.         self = self.goalentity;
  1642.         button_touch ();
  1643.         self = tmp;
  1644.         clearCache (other);
  1645.         other.search_time = (time + MOVETYPE_WALK);
  1646.         other.nextthink = (time + 0.3);
  1647.         return;
  1648.     }
  1649.     if (VERBOSEBOT)
  1650.     {
  1651.         dprint (other.teamname);
  1652.         dprint (other.netname);
  1653.         dprint ("tracking ");
  1654.         dprint (self.goalentity.teamname);
  1655.         dprint (self.goalentity.netname);
  1656.         dprint ("\n");
  1657.     }
  1658.     pth = BestChaseRoute (other, self.goalentity);
  1659.     rnd = ((2000 + (random () * 1000)) + (other.skil * SEARCH_RADIUS));
  1660.     rnd = (rnd - vlen ((other.origin - pth.origin)));
  1661.     if ((rnd < pth.enemylen))
  1662.     {
  1663.         other.search_time = (time - TRUE);
  1664.         return;
  1665.     }
  1666.     random ();
  1667.     rnd = (random () * (other.skil + TRUE));
  1668.     if ((rnd < 0.1))
  1669.     {
  1670.         other.search_time = (time - TRUE);
  1671.         return;
  1672.     }
  1673.     if ((self.classname != "BotTarget"))
  1674.     {
  1675.         objerror ("bad bot target in bot_touch! 2\n");
  1676.     }
  1677.     setorigin (self, pth.origin);
  1678.     other.search_time = (time + MOVETYPE_STEP);
  1679. };
  1680.  
  1681. void () bot_toucheditem =
  1682. {
  1683.     if ((other.goalentity.goalentity == self))
  1684.     {
  1685.         if (VERBOSEBOT)
  1686.         {
  1687.             dprint (other.teamname);
  1688.             dprint (other.netname);
  1689.             dprint (" got to ");
  1690.             dprint (self.classname);
  1691.             dprint ("\n");
  1692.         }
  1693.         other.lefty = (other.lefty - (other.lefty & LOCAL_TIME));
  1694.         other.search_time = (time - TRUE);
  1695.     }
  1696. };
  1697.  
  1698. void (entity bot) bot_triggered =
  1699. {
  1700.     local vector org;
  1701.     local entity Botgoal;
  1702.  
  1703.     Botgoal = bot.goalentity;
  1704.     if ((Botgoal.goalentity != self))
  1705.     {
  1706.         return;
  1707.     }
  1708.     Botgoal.goalentity = find (world, targetname, self.target);
  1709.     if ((Botgoal.goalentity.classname == "light"))
  1710.     {
  1711.         bot.search_time = time;
  1712.         return;
  1713.     }
  1714.     if (Botgoal.goalentity)
  1715.     {
  1716.         bot.search_time = (time + MOVETYPE_WALK);
  1717.         org = ((Botgoal.goalentity.absmax + Botgoal.goalentity.absmin) * 0.5);
  1718.         org_z = (Botgoal.goalentity.absmin_z + TRUE);
  1719.         if ((Botgoal.classname != "BotTarget"))
  1720.         {
  1721.             objerror ("bad bot target in bot_touch! 3\n");
  1722.         }
  1723.         setorigin (Botgoal, org);
  1724.         Botgoal.goalentity.lastbot = bot;
  1725.         Botgoal.goalentity.lasttime = time;
  1726.         if (VERBOSEBOT)
  1727.         {
  1728.             dprint ("now Bot will go after the triggered ");
  1729.             dprint (Botgoal.goalentity.classname);
  1730.             dprint ("\n");
  1731.         }
  1732.     }
  1733. };
  1734. void () aibot_setupchase;
  1735.  
  1736. void () bot_touched =
  1737. {
  1738.     local entity tmp;
  1739.  
  1740.     tmp = self;
  1741.     self = other.goalentity;
  1742.     if ((self.classname != "BotTarget"))
  1743.     {
  1744.         objerror ("bad bot target in bot_touch! 4\n");
  1745.     }
  1746.     if ((self.goalentity == tmp))
  1747.     {
  1748.         t_botmovetarget ();
  1749.     }
  1750.     else
  1751.     {
  1752.         if ((self.goalentity.classname == "door"))
  1753.         {
  1754.             if ((tmp.classname == "door"))
  1755.             {
  1756.                 t_botmovetarget ();
  1757.             }
  1758.         }
  1759.     }
  1760.     self = tmp;
  1761. };
  1762.  
  1763. void () enemy_touched =
  1764. {
  1765.     local entity tmp;
  1766.     local vector org;
  1767.  
  1768.     if (VERBOSEBOT)
  1769.     {
  1770.         dprint (other.enemy.teamname);
  1771.         dprint (other.enemy.netname);
  1772.         dprint (" chasing ");
  1773.         dprint (other.teamname);
  1774.         dprint (other.netname);
  1775.         dprint (" through ");
  1776.         dprint (self.classname);
  1777.         dprint ("!\n");
  1778.     }
  1779.     org = ((self.absmax + self.absmin) * 0.5);
  1780.     org_z = (self.absmin_z + TRUE);
  1781.     if ((self.classname == "door"))
  1782.     {
  1783.         org = other.origin;
  1784.     }
  1785.     tmp = self;
  1786.     self = other.enemy;
  1787.     if ((self.enemy != other))
  1788.     {
  1789.         self = tmp;
  1790.         return;
  1791.     }
  1792.     if ((tmp.classname == "trigger_push"))
  1793.     {
  1794.         endEnemy ();
  1795.         self.search_time = (time + MOVETYPE_STEP);
  1796.         if ((self.goalentity.classname != "BotTarget"))
  1797.         {
  1798.             objerror ("bad bot target in bot_touch! 5\n");
  1799.         }
  1800.         setorigin (self.goalentity, org);
  1801.         self = tmp;
  1802.         return;
  1803.     }
  1804.     if ((self.goalentity.classname != "BotTarget"))
  1805.     {
  1806.         objerror ("ERROR - bad bot target!\n");
  1807.     }
  1808.     setorigin (self.goalentity, org);
  1809.     self.goalentity.goalentity = self.enemy;
  1810.     self.search_time = (time + MOVETYPE_STEP);
  1811.     if ((self.lefty & GETGOODY))
  1812.     {
  1813.         self.lefty = (self.lefty - GETGOODY);
  1814.     }
  1815.     aibot_setupchase ();
  1816.     self = tmp;
  1817. };
  1818.  
  1819.  
  1820.  
  1821. void () halfwalkmove =
  1822. {
  1823.     walkmove (self.strafeyaw, self.strafedist);
  1824.     self.think = self.strafethink;
  1825.     self.nextthink = (time + 0.05);
  1826. };
  1827.  
  1828. float (float s_yaw, float s_dist) botwalkmove =
  1829. {
  1830.     local float halfdist;
  1831.  
  1832.     self.oldorigin = self.origin;
  1833.     if ((self.skil > FL_SWIM))
  1834.     {
  1835.         halfdist = (0.55 * s_dist);
  1836.     }
  1837.     else
  1838.     {
  1839.         halfdist = (0.5 * s_dist);
  1840.     }
  1841.     if (!walkmove (s_yaw, halfdist))
  1842.     {
  1843.         return (FALSE);
  1844.     }
  1845.     self.strafethink = self.think;
  1846.     self.strafeyaw = s_yaw;
  1847.     self.strafedist = halfdist;
  1848.     self.think = halfwalkmove;
  1849.     self.nextthink = (time + 0.05);
  1850.     return (TRUE);
  1851. };
  1852.  
  1853. float (float dist) teleptest =
  1854. {
  1855.     local vector start;
  1856.     local vector up;
  1857.  
  1858.     up = self.origin;
  1859.     start = self.origin;
  1860.     if ((dist < FALSE))
  1861.     {
  1862.         up_z = ((self.absmin_z + dist) - TRUE);
  1863.     }
  1864.     else
  1865.     {
  1866.         up_z = ((self.absmax_z + dist) + TRUE);
  1867.     }
  1868.     traceline (start, up, FALSE, self);
  1869.     if ((trace_fraction < TRUE))
  1870.     {
  1871.         return (FALSE);
  1872.     }
  1873.     start_x = (start_x + FL_INWATER);
  1874.     start_y = (start_y + FL_INWATER);
  1875.     up_x = (up_x + FL_INWATER);
  1876.     up_y = (up_y + FL_INWATER);
  1877.     traceline (start, up, FALSE, self);
  1878.     if ((trace_fraction < TRUE))
  1879.     {
  1880.         return (FALSE);
  1881.     }
  1882.     start_x = (start_x - FL_MONSTER);
  1883.     up_x = (up_x - FL_MONSTER);
  1884.     traceline (start, up, FALSE, self);
  1885.     if ((trace_fraction < TRUE))
  1886.     {
  1887.         return (FALSE);
  1888.     }
  1889.     start_y = (start_y - FL_MONSTER);
  1890.     up_y = (up_y - FL_MONSTER);
  1891.     traceline (start, up, FALSE, self);
  1892.     if ((trace_fraction < TRUE))
  1893.     {
  1894.         return (FALSE);
  1895.     }
  1896.     start_x = (start_x + FL_MONSTER);
  1897.     up_x = (up_x + FL_MONSTER);
  1898.     traceline (start, up, FALSE, self);
  1899.     if ((trace_fraction < TRUE))
  1900.     {
  1901.         return (FALSE);
  1902.     }
  1903.     start = self.origin;
  1904.     start_z = up_z;
  1905.     up = start;
  1906.     start_x = (start_x + FL_INWATER);
  1907.     up_x = (up_x - FL_INWATER);
  1908.     traceline (start, up, FALSE, self);
  1909.     if ((trace_fraction < TRUE))
  1910.     {
  1911.         return (FALSE);
  1912.     }
  1913.     start = self.origin;
  1914.     start_z = up_z;
  1915.     up = start;
  1916.     start_y = (start_y + FL_INWATER);
  1917.     up_y = (up_y - FL_INWATER);
  1918.     traceline (start, up, FALSE, self);
  1919.     if ((trace_fraction < TRUE))
  1920.     {
  1921.         return (FALSE);
  1922.     }
  1923.     return (TRUE);
  1924. };
  1925.  
  1926. float (float dist) waterupz =
  1927. {
  1928.     local vector start;
  1929.     local vector up;
  1930.  
  1931.     if (!teleptest (dist))
  1932.     {
  1933.         return (FALSE);
  1934.     }
  1935.     up = self.origin;
  1936.     up_z = (up_z + dist);
  1937.     setorigin (self, up);
  1938.     return (TRUE);
  1939. };
  1940.  
  1941. float (float dist) waterdownz =
  1942. {
  1943.     local vector up;
  1944.     local vector start;
  1945.  
  1946.     if (!teleptest ((CONTENT_EMPTY * dist)))
  1947.     {
  1948.         return (FALSE);
  1949.     }
  1950.     up = self.origin;
  1951.     up_z = (up_z - dist);
  1952.     setorigin (self, up);
  1953.     return (TRUE);
  1954. };
  1955.  
  1956. float (vector jmpv) Botjump =
  1957. {
  1958.     if ((self.flags & FL_ONGROUND))
  1959.     {
  1960.         self.flags = (self.flags - FL_ONGROUND);
  1961.     }
  1962.     self.velocity = jmpv;
  1963.     return (TRUE);
  1964. };
  1965.  
  1966. float (vector jmpv) Botwaterjump =
  1967. {
  1968.     if ((self.flags & FL_ONGROUND))
  1969.     {
  1970.         self.flags = (self.flags - FL_ONGROUND);
  1971.     }
  1972.     if (!waterupz (45))
  1973.     {
  1974.         return (FALSE);
  1975.     }
  1976.     jmpv_z = 200;
  1977.     self.velocity = jmpv;
  1978.     if ((self.flags & FL_SWIM))
  1979.     {
  1980.         self.flags = (self.flags - FL_SWIM);
  1981.     }
  1982.     if ((self.flags & FL_INWATER))
  1983.     {
  1984.         self.flags = (self.flags - FL_INWATER);
  1985.     }
  1986.     self.teleport_time = (time + 0.7);
  1987.     return (TRUE);
  1988. };
  1989. float (entity targ) Swimto;
  1990.  
  1991. float (vector spot) CheckLavaOrLow =
  1992. {
  1993.     local float lnd;
  1994.     local float boost;
  1995.     local vector spot2;
  1996.  
  1997.     lnd = pointcontents (spot);
  1998.     if (((lnd == CONTENT_LAVA) || (lnd == CONTENT_SLIME)))
  1999.     {
  2000.         return (TRUE);
  2001.     }
  2002.     spot2 = spot;
  2003.     spot2_z = (spot_z + FL_CLIENT);
  2004.     lnd = pointcontents (spot2);
  2005.     if (((lnd == CONTENT_LAVA) || (lnd == CONTENT_SLIME)))
  2006.     {
  2007.         return (TRUE);
  2008.     }
  2009.     if ((lnd != CONTENT_WATER))
  2010.     {
  2011.         boost = (MAXJUMP + TRUE);
  2012.         if ((self.goalentity.goalentity.classname == "func_button"))
  2013.         {
  2014.             boost = ((boost + self.maxs_z) - TRUE);
  2015.         }
  2016.         if (((spot_z + boost) < self.goalentity.origin_z))
  2017.         {
  2018.             return (TRUE);
  2019.         }
  2020.     }
  2021.     else
  2022.     {
  2023.         traceline (spot2, self.goalentity.absmin, TRUE, self);
  2024.         if (trace_inopen)
  2025.         {
  2026.             if (((spot_z + 45) > self.goalentity.origin_z))
  2027.             {
  2028.                 return (FALSE);
  2029.             }
  2030.             return (TRUE);
  2031.         }
  2032.         if ((trace_fraction == TRUE))
  2033.         {
  2034.             return (FALSE);
  2035.         }
  2036.         return (TRUE);
  2037.     }
  2038.     return (FALSE);
  2039. };
  2040.  
  2041. float (vector middle) checkLanding =
  2042. {
  2043.     local float goodcnt;
  2044.     local vector spot;
  2045.     local vector center;
  2046.  
  2047.     center = middle;
  2048.     spot = middle;
  2049.     spot_x = (spot_x + MOVETYPE_TOSS);
  2050.     if ((pointcontents (spot) == CONTENT_SOLID))
  2051.     {
  2052.         center_x = (center_x - MOVETYPE_TOSS);
  2053.     }
  2054.     spot_x = (spot_x - 12);
  2055.     if ((pointcontents (spot) == CONTENT_SOLID))
  2056.     {
  2057.         center_x = (center_x + MOVETYPE_TOSS);
  2058.     }
  2059.     spot = middle;
  2060.     spot_y = (spot_y + MOVETYPE_TOSS);
  2061.     if ((pointcontents (spot) == CONTENT_SOLID))
  2062.     {
  2063.         center_y = (center_y - MOVETYPE_TOSS);
  2064.     }
  2065.     spot_y = (spot_y - 12);
  2066.     if ((pointcontents (spot) == CONTENT_SOLID))
  2067.     {
  2068.         center_y = (center_y + MOVETYPE_TOSS);
  2069.     }
  2070.     spot = center;
  2071.     spot_z = dropline (spot);
  2072.     goodcnt = MOVETYPE_FLY;
  2073.     if (CheckLavaOrLow (spot))
  2074.     {
  2075.         return (FALSE);
  2076.     }
  2077.     spot = center;
  2078.     spot_x = (spot_x + MOVETYPE_TOSS);
  2079.     spot_z = dropline (spot);
  2080.     if (CheckLavaOrLow (spot))
  2081.     {
  2082.         goodcnt = (goodcnt - TRUE);
  2083.     }
  2084.     spot = center;
  2085.     spot_x = (spot_x - MOVETYPE_TOSS);
  2086.     spot_z = dropline (spot);
  2087.     if (CheckLavaOrLow (spot))
  2088.     {
  2089.         goodcnt = (goodcnt - TRUE);
  2090.     }
  2091.     spot = center;
  2092.     spot_y = (spot_y + MOVETYPE_TOSS);
  2093.     spot_z = dropline (spot);
  2094.     if (CheckLavaOrLow (spot))
  2095.     {
  2096.         goodcnt = (goodcnt - TRUE);
  2097.     }
  2098.     spot = center;
  2099.     spot_y = (spot_y - MOVETYPE_TOSS);
  2100.     spot_z = dropline (spot);
  2101.     if (CheckLavaOrLow (spot))
  2102.     {
  2103.         goodcnt = (goodcnt - TRUE);
  2104.     }
  2105.     if ((goodcnt > MOVETYPE_WALK))
  2106.     {
  2107.         return (TRUE);
  2108.     }
  2109.     return (FALSE);
  2110. };
  2111.  
  2112. float (float dist) JumpUpToPush =
  2113. {
  2114.     local float len;
  2115.     local vector botxy;
  2116.     local vector goalxy;
  2117.     local vector xydir;
  2118.     local vector jumpv;
  2119.  
  2120.     botxy = self.origin;
  2121.     botxy_z = FALSE;
  2122.     goalxy = self.goalentity.origin;
  2123.     goalxy_z = FALSE;
  2124.     xydir = normalize ((goalxy - botxy));
  2125.     len = vlen ((goalxy - botxy));
  2126.     if ((len < 25))
  2127.     {
  2128.         jumpv = (xydir * KINDA_WANT);
  2129.         jumpv_z = 270;
  2130.         Botjump (jumpv);
  2131.         return (TRUE);
  2132.     }
  2133.     if ((len < 80))
  2134.     {
  2135.         jumpv = (xydir * (len / LEVELJUMPTIME));
  2136.         jumpv_z = 270;
  2137.         Botjump (jumpv);
  2138.         return (TRUE);
  2139.     }
  2140.     return (FALSE);
  2141. };
  2142.  
  2143. float (float vz, float dist, float imagine) Bot_tryjump =
  2144. {
  2145.     local float timetofloor;
  2146.     local float tvel;
  2147.     local float dis;
  2148.     local float diffz;
  2149.     local float diffxy;
  2150.     local float NOTLAND;
  2151.     local float lnd;
  2152.     local float len;
  2153.     local float depth;
  2154.     local float wlevel;
  2155.     local float velz;
  2156.     local float ht;
  2157.     local float frac;
  2158.     local vector botxy;
  2159.     local vector goalxy;
  2160.     local vector xydir;
  2161.     local vector top;
  2162.     local vector bottom;
  2163.     local vector jumpv;
  2164.     local vector newtop;
  2165.     local vector newbottom;
  2166.     local vector back;
  2167.     local vector front;
  2168.     local vector dir;
  2169.     local vector start;
  2170.     local string tmp;
  2171.     local entity botTarget;
  2172.  
  2173.     if (!(self.flags & (FL_ONGROUND + FL_SWIM)))
  2174.     {
  2175.         return (FALSE);
  2176.     }
  2177.     wlevel = CheckWaterLevel ();
  2178.     if ((wlevel > FL_SWIM))
  2179.     {
  2180.         return (FALSE);
  2181.     }
  2182.     if (!FacingIdeal ())
  2183.     {
  2184.         ChangeYaw ();
  2185.         if (!FacingIdeal ())
  2186.         {
  2187.             ChangeYaw ();
  2188.             if (!FacingIdeal ())
  2189.             {
  2190.                 ChangeYaw ();
  2191.             }
  2192.         }
  2193.     }
  2194.     makevectors (self.angles);
  2195.     start = (self.origin + (FL_INWATER * v_forward));
  2196.     botTarget = self.goalentity;
  2197.     velz = vz;
  2198.     if ((wlevel >= TRUE))
  2199.     {
  2200.         if ((velz > 200))
  2201.         {
  2202.             velz = 200;
  2203.         }
  2204.     }
  2205.     if ((wlevel == FL_SWIM))
  2206.     {
  2207.         if ((botTarget.origin_z < self.origin_z))
  2208.         {
  2209.             return (FALSE);
  2210.         }
  2211.         start_z = (start_z + 45);
  2212.     }
  2213.     botxy = self.origin;
  2214.     botxy_z = FALSE;
  2215.     diffz = ((start_z - botTarget.origin_z) + TRUE);
  2216.     if ((diffz < (CONTENT_EMPTY * MAXJUMP)))
  2217.     {
  2218.         if ((botTarget.goalentity.classname != "trigger_push"))
  2219.         {
  2220.             return (FALSE);
  2221.         }
  2222.         else
  2223.         {
  2224.             if ((diffz < FALSE))
  2225.             {
  2226.                 if (JumpUpToPush (dist))
  2227.                 {
  2228.                     return (TRUE);
  2229.                 }
  2230.             }
  2231.         }
  2232.     }
  2233.     dis = dist;
  2234.     goalxy = botTarget.origin;
  2235.     if ((botTarget.goalentity.classname == "train"))
  2236.     {
  2237.         goalxy = (goalxy + (LEVELJUMPTIME * botTarget.goalentity.velocity));
  2238.     }
  2239.     lnd = pointcontents (goalxy);
  2240.     if (((lnd == CONTENT_LAVA) || (lnd == CONTENT_SLIME)))
  2241.     {
  2242.         return (FALSE);
  2243.     }
  2244.     goalxy_z = FALSE;
  2245.     xydir = normalize ((goalxy - botxy));
  2246.     diffxy = vlen ((goalxy - botxy));
  2247.     if ((wlevel == FL_SWIM))
  2248.     {
  2249.         if ((diffxy > (MOVETYPE_WALK * BOTSPEED)))
  2250.         {
  2251.             diffxy = (MOVETYPE_WALK * BOTSPEED);
  2252.         }
  2253.     }
  2254.     bottom = (start + self.view_ofs);
  2255.     top = (bottom + (xydir * dis));
  2256.     top_z = (top_z + (0.1 * (velz - GRAVITY)));
  2257.     traceline (bottom, top, TRUE, self);
  2258.     if ((trace_fraction != TRUE))
  2259.     {
  2260.         if ((velz > (GRAVITY + 180)))
  2261.         {
  2262.             return (Bot_tryjump ((velz - GRAVITY), dist, imagine));
  2263.         }
  2264.         else
  2265.         {
  2266.             return (FALSE);
  2267.         }
  2268.     }
  2269.     bottom = (start - (FL_INWATER * v_forward));
  2270.     bottom_z = (bottom_z + self.mins_z);
  2271.     top = (bottom + ((xydir * dis) * FL_SWIM));
  2272.     top_z = ((top_z + (0.2 * (velz - GRAVITY))) - (0.1 * GRAVITY));
  2273.     traceline (bottom, top, TRUE, self);
  2274.     if ((trace_fraction != TRUE))
  2275.     {
  2276.         if ((diffxy > (1.9 * BOTSPEED)))
  2277.         {
  2278.             diffxy = (1.9 * BOTSPEED);
  2279.         }
  2280.         top = (bottom + (xydir * dis));
  2281.         top_z = ((top_z + (0.2 * (velz - GRAVITY))) - (0.1 * GRAVITY));
  2282.         traceline (bottom, top, TRUE, self);
  2283.         if ((trace_fraction != TRUE))
  2284.         {
  2285.             if ((diffxy > (0.9 * BOTSPEED)))
  2286.             {
  2287.                 diffxy = (0.9 * BOTSPEED);
  2288.             }
  2289.             velz = 290;
  2290.         }
  2291.     }
  2292.     timetofloor = FALSE;
  2293.     tvel = velz;
  2294.     if ((diffz < FALSE))
  2295.     {
  2296.         timetofloor = 0.3;
  2297.     }
  2298.     else
  2299.     {
  2300.         while ((diffz > FALSE))
  2301.         {
  2302.             timetofloor = (timetofloor + 0.1);
  2303.             tvel = (tvel - GRAVITY);
  2304.             diffz = (diffz + (tvel * 0.1));
  2305.         }
  2306.         timetofloor = (timetofloor - (diffz / tvel));
  2307.     }
  2308.     if ((diffxy < ((dis * MOVETYPE_BOUNCE) * timetofloor)))
  2309.     {
  2310.         jumpv = (xydir * (diffxy / timetofloor));
  2311.     }
  2312.     else
  2313.     {
  2314.         jumpv = (xydir * (MOVETYPE_BOUNCE * dis));
  2315.         if (imagine)
  2316.         {
  2317.             return (FALSE);
  2318.         }
  2319.     }
  2320.     tvel = velz;
  2321.     bottom = start;
  2322.     bottom_z = (bottom_z + self.mins_z);
  2323.     ht = (self.view_ofs_z - self.mins_z);
  2324.     NOTLAND = TRUE;
  2325.     while (NOTLAND)
  2326.     {
  2327.         tvel = (tvel - GRAVITY);
  2328.         newbottom = (bottom + (jumpv * 0.1));
  2329.         newbottom_z = (newbottom_z + (tvel * 0.1));
  2330.         traceline (bottom, newbottom, TRUE, self);
  2331.         frac = trace_fraction;
  2332.         if ((trace_fraction == TRUE))
  2333.         {
  2334.             newtop = newbottom;
  2335.             top = bottom;
  2336.             top_z = (top_z + ht);
  2337.             newtop_z = (newtop_z + ht);
  2338.             traceline (top, newtop, TRUE, self);
  2339.             if ((trace_fraction == TRUE))
  2340.             {
  2341.                 traceline (newbottom, newtop, TRUE, self);
  2342.             }
  2343.             if ((trace_fraction == TRUE))
  2344.             {
  2345.                 top = (top + (FL_INWATER * v_right));
  2346.                 newtop = (newtop + (FL_INWATER * v_right));
  2347.                 traceline (top, newtop, TRUE, self);
  2348.             }
  2349.             if ((trace_fraction == TRUE))
  2350.             {
  2351.                 top = (top - (FL_MONSTER * v_right));
  2352.                 newtop = (newtop - (FL_MONSTER * v_right));
  2353.                 traceline (top, newtop, TRUE, self);
  2354.             }
  2355.             if ((trace_fraction != TRUE))
  2356.             {
  2357.                 frac = 0.1;
  2358.             }
  2359.         }
  2360.         if ((trace_fraction != TRUE))
  2361.         {
  2362.             dir = normalize ((newbottom - bottom));
  2363.             len = vlen ((newbottom - bottom));
  2364.             newbottom = (bottom + ((dir * len) * frac));
  2365.             newbottom_z = (newbottom_z + KINDA_WANT);
  2366.             if (!checkLanding ((newbottom - (FL_INWATER * v_forward))))
  2367.             {
  2368.                 return (FALSE);
  2369.             }
  2370.             NOTLAND = FALSE;
  2371.         }
  2372.         if (NOTLAND)
  2373.         {
  2374.             if (CheckLavaOrLow (newbottom))
  2375.             {
  2376.                 return (FALSE);
  2377.             }
  2378.         }
  2379.         lnd = pointcontents (newbottom);
  2380.         if ((lnd == CONTENT_WATER))
  2381.         {
  2382.             NOTLAND = FALSE;
  2383.         }
  2384.         bottom = newbottom;
  2385.     }
  2386.     jumpv_z = velz;
  2387.     if (imagine)
  2388.     {
  2389.         if ((wlevel == FL_SWIM))
  2390.         {
  2391.             return (teleptest (45));
  2392.         }
  2393.         return (TRUE);
  2394.     }
  2395.     if ((wlevel == FL_SWIM))
  2396.     {
  2397.         return (Botwaterjump (jumpv));
  2398.     }
  2399.     if ((newbottom_z < (self.absmin_z - MAXJUMP)))
  2400.     {
  2401.         clearCache (self);
  2402.     }
  2403.     return (Botjump (jumpv));
  2404. };
  2405.  
  2406. float (float dist) waterupdown =
  2407. {
  2408.     local float wlevel;
  2409.     local float dis;
  2410.     local float rnd;
  2411.     local float zbottom;
  2412.  
  2413.     dis = KINDA_WANT;
  2414.     wlevel = CheckWaterLevel ();
  2415.     if ((wlevel < FL_SWIM))
  2416.     {
  2417.         return (FALSE);
  2418.     }
  2419.     if ((self.absmin_z > self.goalentity.origin_z))
  2420.     {
  2421.         if ((dis > KINDA_WANT))
  2422.         {
  2423.             dis = KINDA_WANT;
  2424.         }
  2425.         if (waterdownz (dis))
  2426.         {
  2427.             return (TRUE);
  2428.         }
  2429.         if (waterdownz ((dis * 0.5)))
  2430.         {
  2431.             return (TRUE);
  2432.         }
  2433.         if (waterdownz ((dis * 0.2)))
  2434.         {
  2435.             return (TRUE);
  2436.         }
  2437.     }
  2438.     if ((wlevel == MOVETYPE_WALK))
  2439.     {
  2440.         if ((self.absmin_z < self.goalentity.origin_z))
  2441.         {
  2442.             dis = (self.goalentity.origin_z - self.absmin_z);
  2443.             if ((dis > KINDA_WANT))
  2444.             {
  2445.                 dis = KINDA_WANT;
  2446.             }
  2447.             if (waterupz (dis))
  2448.             {
  2449.                 return (TRUE);
  2450.             }
  2451.             if (waterupz ((dis * 0.5)))
  2452.             {
  2453.                 return (TRUE);
  2454.             }
  2455.             if (waterupz ((dis * 0.2)))
  2456.             {
  2457.                 return (TRUE);
  2458.             }
  2459.         }
  2460.     }
  2461.     return (FALSE);
  2462. };
  2463.  
  2464. void (float dist) strafemove =
  2465. {
  2466.     local float ofs;
  2467.     local float rnd;
  2468.  
  2469.     if ((self.flags & FL_SWIM))
  2470.     {
  2471.         if (waterupdown (dist))
  2472.         {
  2473.             return;
  2474.         }
  2475.     }
  2476.     ofs = 90;
  2477.     rnd = random ();
  2478.     if (self.enemy)
  2479.     {
  2480.         self.strafeonly = MOVETYPE_FLY;
  2481.         if ((self.lefty & STRAFE_DIR))
  2482.         {
  2483.             ofs = (CONTENT_EMPTY * ofs);
  2484.         }
  2485.     }
  2486.     else
  2487.     {
  2488.         if ((rnd < 0.5))
  2489.         {
  2490.             ofs = (CONTENT_EMPTY * ofs);
  2491.         }
  2492.     }
  2493.     if (walkmove ((self.ideal_yaw + ofs), dist))
  2494.     {
  2495.         return;
  2496.     }
  2497.     if (self.enemy)
  2498.     {
  2499.         return;
  2500.     }
  2501.     ofs = (CONTENT_EMPTY * ofs);
  2502.     if (walkmove ((self.ideal_yaw + ofs), dist))
  2503.     {
  2504.         return;
  2505.     }
  2506.     if ((self.flags & (FL_INWATER + FL_ONGROUND)))
  2507.     {
  2508.         self.search_time = (self.search_time - 0.3);
  2509.     }
  2510. };
  2511.  
  2512. void (float dist, float wlevel) BotUnderwaterMove =
  2513. {
  2514.     local float rng;
  2515.     local float oldrng;
  2516.     local float rnd;
  2517.  
  2518.     rnd = random ();
  2519.     if ((rnd < 0.75))
  2520.     {
  2521.         oldrng = vlen ((self.origin - self.goalentity.origin));
  2522.         movetogoal (dist);
  2523.         rng = vlen ((self.origin - self.goalentity.origin));
  2524.         if ((oldrng > rng))
  2525.         {
  2526.             return;
  2527.         }
  2528.         if ((wlevel == FL_SWIM))
  2529.         {
  2530.             if (Bot_tryjump (200, dist, FALSE))
  2531.             {
  2532.                 return;
  2533.             }
  2534.         }
  2535.     }
  2536.     strafemove (dist);
  2537. };
  2538.  
  2539. float (float dist) trysidestep =
  2540. {
  2541.     local vector dir;
  2542.     local vector start;
  2543.  
  2544.     dir = (self.goalentity.origin - self.origin);
  2545.     dir_z = FALSE;
  2546.     dir = normalize (dir);
  2547.     start = self.origin;
  2548.     start_z = (self.origin_z + (self.view_ofs_z * 0.5));
  2549.     traceline (start, (start + (BOTSPEED * dir)), FALSE, self);
  2550.     if ((trace_fraction != TRUE))
  2551.     {
  2552.         strafemove ((dist * 0.6));
  2553.         return (TRUE);
  2554.     }
  2555.     makevectors (self.angles);
  2556.     start = (start + (v_right * 15));
  2557.     traceline (start, (start + (BOTSPEED * dir)), FALSE, self);
  2558.     if ((trace_fraction != TRUE))
  2559.     {
  2560.         if (walkmove ((self.ideal_yaw - 90), (dist * 0.6)))
  2561.         {
  2562.             return (TRUE);
  2563.         }
  2564.     }
  2565.     start = (start - (v_right * SVC_INTERMISSION));
  2566.     traceline (start, (start + (BOTSPEED * dir)), FALSE, self);
  2567.     if ((trace_fraction != TRUE))
  2568.     {
  2569.         if (walkmove ((self.ideal_yaw + 90), (dist * 0.6)))
  2570.         {
  2571.             return (TRUE);
  2572.         }
  2573.     }
  2574.     return (FALSE);
  2575. };
  2576.  
  2577. float (float dist) testmove =
  2578. {
  2579.     local float rng;
  2580.     local float oldrng;
  2581.  
  2582.     oldrng = vlen ((self.origin - self.goalentity.origin));
  2583.     movetogoal (dist);
  2584.     rng = vlen ((self.origin - self.goalentity.origin));
  2585.     if ((rng < oldrng))
  2586.     {
  2587.         return (TRUE);
  2588.     }
  2589.     return (FALSE);
  2590. };
  2591.  
  2592. void (float dist) BotmovetoWindTunnel =
  2593. {
  2594.     if (testmove (dist))
  2595.     {
  2596.         return;
  2597.     }
  2598.     if (trysidestep (dist))
  2599.     {
  2600.         return;
  2601.     }
  2602.     if (Bot_tryjump (270, dist, FALSE))
  2603.     {
  2604.         return;
  2605.     }
  2606.     strafemove ((dist * 0.5));
  2607.     return;
  2608. };
  2609.  
  2610. void (float dist) BotmovetoVisiblegoal =
  2611. {
  2612.     if (walkmove (self.ideal_yaw, FL_CLIENT))
  2613.     {
  2614.         botwalkmove (self.ideal_yaw, (dist - FL_CLIENT));
  2615.         return;
  2616.     }
  2617.     if (walkmove ((self.ideal_yaw + 45), FL_CLIENT))
  2618.     {
  2619.         movetogoal ((dist - FL_CLIENT));
  2620.         return;
  2621.     }
  2622.     if (walkmove ((self.ideal_yaw - 45), FL_CLIENT))
  2623.     {
  2624.         movetogoal ((dist - FL_CLIENT));
  2625.         return;
  2626.     }
  2627.     if (trysidestep (dist))
  2628.     {
  2629.         return;
  2630.     }
  2631.     if (Bot_tryjump (270, dist, FALSE))
  2632.     {
  2633.         return;
  2634.     }
  2635.     strafemove ((dist * 0.5));
  2636.     return;
  2637. };
  2638.  
  2639. void (float dist) Botmovetogoal =
  2640. {
  2641.     local entity Botgoal;
  2642.     local float wlevel;
  2643.  
  2644.     self.oldorigin = self.origin;
  2645.     Botgoal = self.goalentity;
  2646.     self.ideal_yaw = vectoyaw ((Botgoal.origin - self.origin));
  2647.     ChangeYaw ();
  2648.     if ((self.flags & FL_INWATER))
  2649.     {
  2650.         wlevel = CheckWaterLevel ();
  2651.         if ((wlevel > TRUE))
  2652.         {
  2653.             BotUnderwaterMove ((dist * 0.8), wlevel);
  2654.             return;
  2655.         }
  2656.     }
  2657.     if ((Botgoal.goalentity.classname == "trigger_push"))
  2658.     {
  2659.         BotmovetoWindTunnel (dist);
  2660.         return;
  2661.     }
  2662.     if (Spotvisible (Botgoal))
  2663.     {
  2664.         BotmovetoVisiblegoal (dist);
  2665.         return;
  2666.     }
  2667.     if (testmove (dist))
  2668.     {
  2669.         return;
  2670.     }
  2671.     strafemove ((dist * 0.8));
  2672.     return;
  2673. };
  2674.  
  2675.  
  2676. entity () noisetarget =
  2677. {
  2678.     local entity targ;
  2679.  
  2680.     targ = spawn ();
  2681.     targ.classname = "NoiseTarget";
  2682.     targ.solid = SOLID_NOT;
  2683.     setsize (targ, '-8 -8 -8', '8 8 8');
  2684.     return (targ);
  2685. };
  2686.  
  2687. void () removenoise =
  2688. {
  2689.     NOISEQUEUE.goalentity = world;
  2690.     NOISEQUEUE.movetarget = world;
  2691. };
  2692.  
  2693. void (entity noisemaker, entity noiseobject) signalnoise =
  2694. {
  2695.     if ((noisemaker.classname != "player"))
  2696.     {
  2697.         return;
  2698.     }
  2699.     if (!NOISEQUEUE)
  2700.     {
  2701.         return;
  2702.     }
  2703.     NOISEQUEUE.goalentity = noisemaker;
  2704.     NOISEQUEUE.movetarget = noiseobject;
  2705.     NOISEQUEUE.think = removenoise;
  2706.     NOISEQUEUE.nextthink = (time + TRUE);
  2707. };
  2708.  
  2709. float (entity e) hearnoise =
  2710. {
  2711.     local float rnd;
  2712.  
  2713.     if ((self.skil < TRUE))
  2714.     {
  2715.         return (FALSE);
  2716.     }
  2717.     if ((self.skil < FL_SWIM))
  2718.     {
  2719.         rnd = (random () + 0.9);
  2720.         if ((self.skil < rnd))
  2721.         {
  2722.             return (FALSE);
  2723.         }
  2724.     }
  2725.     if ((NOISEQUEUE.goalentity == e))
  2726.     {
  2727.         dprint (self.teamname);
  2728.         dprint (self.classname);
  2729.         dprint (" heard ");
  2730.         dprint (NOISEQUEUE.goalentity.netname);
  2731.         if ((NOISEQUEUE.movetarget.classname == "player"))
  2732.         {
  2733.             dprint (" shoot\n");
  2734.         }
  2735.         else
  2736.         {
  2737.             dprint (" trigger ");
  2738.             dprint (NOISEQUEUE.movetarget.classname);
  2739.             dprint ("\n");
  2740.         }
  2741.         return (TRUE);
  2742.     }
  2743.     return (FALSE);
  2744. };
  2745.  
  2746. float (entity e) heardistantnoise =
  2747. {
  2748.     return (FALSE);
  2749. };
  2750.  
  2751.  
  2752.  
  2753. float (entity targ) botrange =
  2754. {
  2755.     local vector spot1;
  2756.     local vector spot2;
  2757.     local float mel;
  2758.     local float r;
  2759.  
  2760.     spot1 = (self.origin + self.view_ofs);
  2761.     spot2 = (targ.origin + targ.view_ofs);
  2762.     r = vlen ((spot1 - spot2));
  2763.     mel = ((180 - (self.health * 0.5)) - (self.armorvalue * self.armortype));
  2764.     if ((self.items & IT_QUAD))
  2765.     {
  2766.         mel = (FL_SWIM * mel);
  2767.     }
  2768.     if ((teamplay == TRUE))
  2769.     {
  2770.         mel = 60;
  2771.     }
  2772.     if ((r < mel))
  2773.     {
  2774.         return (RANGE_MELEE);
  2775.     }
  2776.     else
  2777.     {
  2778.         if ((r < SEARCH_RADIUS))
  2779.         {
  2780.             return (RANGE_NEAR);
  2781.         }
  2782.         else
  2783.         {
  2784.             if ((r < 1000))
  2785.             {
  2786.                 return (RANGE_MID);
  2787.             }
  2788.         }
  2789.     }
  2790.     return (RANGE_FAR);
  2791. };
  2792.  
  2793. float (entity targ) infrontofbot =
  2794. {
  2795.     local vector vec;
  2796.     local vector xydir;
  2797.     local float fov;
  2798.     local float dot;
  2799.     local float lnd;
  2800.  
  2801.     if ((self.skil == MOVETYPE_WALK))
  2802.     {
  2803.         return (TRUE);
  2804.     }
  2805.     lnd = pointcontents ((self.origin + self.view_ofs));
  2806.     if ((lnd != CONTENT_WATER))
  2807.     {
  2808.         if ((self.skil < FL_SWIM))
  2809.         {
  2810.             xydir = (targ.origin - self.origin);
  2811.             xydir_z = FALSE;
  2812.             dot = vlen (xydir);
  2813.             fov = ((targ.origin_z - self.origin_z) * (FL_SWIM - (0.75 * self.skil)));
  2814.             if ((fov < FALSE))
  2815.             {
  2816.                 fov = (-0.8 * fov);
  2817.             }
  2818.             if (((fov > 150) && (dot < fov)))
  2819.             {
  2820.                 return (FALSE);
  2821.             }
  2822.         }
  2823.     }
  2824.     makevectors (self.angles);
  2825.     vec = normalize ((targ.origin - self.origin));
  2826.     dot = (vec * v_forward);
  2827.     fov = (0.7 - (self.skil * 0.28));
  2828.     if ((dot > fov))
  2829.     {
  2830.         return (TRUE);
  2831.     }
  2832.     if ((lnd == CONTENT_WATER))
  2833.     {
  2834.         if ((dot > FALSE))
  2835.         {
  2836.             return (TRUE);
  2837.         }
  2838.     }
  2839.     return (FALSE);
  2840. };
  2841.  
  2842. float (entity targ) Swimto =
  2843. {
  2844.     local vector spot1;
  2845.     local vector spot2;
  2846.     local float lnd;
  2847.  
  2848.     spot1 = (self.origin + self.view_ofs);
  2849.     spot2 = targ.absmin;
  2850.     lnd = pointcontents (spot2);
  2851.     if ((lnd != CONTENT_WATER))
  2852.     {
  2853.         if ((spot2_z > (spot1_z + MAXJUMP)))
  2854.         {
  2855.             return (FALSE);
  2856.         }
  2857.     }
  2858.     traceline (spot1, spot2, TRUE, self);
  2859.     if ((trace_fraction == TRUE))
  2860.     {
  2861.         return (TRUE);
  2862.     }
  2863.     if ((trace_ent == targ))
  2864.     {
  2865.         return (TRUE);
  2866.     }
  2867.     return (FALSE);
  2868. };
  2869.  
  2870. float (entity targ) Spotvisible =
  2871. {
  2872.     local vector spot1;
  2873.     local vector spot2;
  2874.     local string t1;
  2875.  
  2876.     spot1 = (self.origin + self.view_ofs);
  2877.     spot2 = ((targ.absmin + targ.absmax) * 0.5);
  2878.     traceline (spot1, spot2, TRUE, self);
  2879.     if ((trace_fraction == TRUE))
  2880.     {
  2881.         return (TRUE);
  2882.     }
  2883.     if ((trace_ent == targ))
  2884.     {
  2885.         return (TRUE);
  2886.     }
  2887.     return (FALSE);
  2888. };
  2889.  
  2890. float (entity targ) enemyvisible =
  2891. {
  2892.     local vector spot1;
  2893.     local vector spot2;
  2894.  
  2895.     if (visible (targ))
  2896.     {
  2897.         return (TRUE);
  2898.     }
  2899.     spot1 = (self.origin + self.view_ofs);
  2900.     spot2 = targ.origin;
  2901.     traceline (spot1, spot2, TRUE, self);
  2902.     if ((trace_inopen && trace_inwater))
  2903.     {
  2904.         return (FALSE);
  2905.     }
  2906.     if ((trace_fraction == TRUE))
  2907.     {
  2908.         return (TRUE);
  2909.     }
  2910.     return (FALSE);
  2911. };
  2912.  
  2913. float (entity targ) Platvisible =
  2914. {
  2915.     local vector spot1;
  2916.     local vector spot2;
  2917.     local string t1;
  2918.  
  2919.     spot1 = (self.origin + self.view_ofs);
  2920.     spot2 = ((targ.absmin + targ.absmax) * 0.5);
  2921.     spot2_z = (targ.absmax_z + MOVETYPE_WALK);
  2922.     traceline (spot1, spot2, TRUE, self);
  2923.     if ((trace_fraction == TRUE))
  2924.     {
  2925.         return (TRUE);
  2926.     }
  2927.     if ((trace_ent == targ))
  2928.     {
  2929.         return (TRUE);
  2930.     }
  2931.     return (FALSE);
  2932. };
  2933.  
  2934. float (vector spot) dropline =
  2935. {
  2936.     local float drop;
  2937.     local vector spot2;
  2938.     local string tmp;
  2939.  
  2940.     spot2 = spot;
  2941.     spot2_z = (spot2_z - 500);
  2942.     traceline (spot, spot2, TRUE, self);
  2943.     drop = (spot_z - (trace_fraction * 500));
  2944.     return (drop);
  2945. };
  2946.  
  2947. float (entity a, entity b, float bmaxjump) BotWalkable =
  2948. {
  2949.     local vector spot1;
  2950.     local vector dir;
  2951.     local vector borg;
  2952.     local float tests;
  2953.     local float okpath;
  2954.     local float flr;
  2955.     local float goalheight;
  2956.  
  2957.     if ((b.pathtype != DROPPED))
  2958.     {
  2959.         borg = ((b.absmin + b.absmax) * 0.5);
  2960.         borg_z = (b.absmin_z + TRUE);
  2961.     }
  2962.     else
  2963.     {
  2964.         borg = b.origin;
  2965.     }
  2966.     spot1 = a.origin;
  2967.     dir = normalize ((borg - a.origin));
  2968.     dir = (((dir * LEVELJUMPTIME) * BOTSPEED) * 6.5);
  2969.     tests = vlen ((borg - a.origin));
  2970.     tests = (tests / ((LEVELJUMPTIME * BOTSPEED) * 6.5));
  2971.     if ((b.pathtype == DROPPED))
  2972.     {
  2973.         goalheight = (borg_z + self.mins_z);
  2974.     }
  2975.     else
  2976.     {
  2977.         goalheight = borg_z;
  2978.     }
  2979.     while ((tests > TRUE))
  2980.     {
  2981.         okpath = TRUE;
  2982.         spot1 = (spot1 + dir);
  2983.         tests = (tests - TRUE);
  2984.         flr = dropline (spot1);
  2985.         if (((flr + bmaxjump) < goalheight))
  2986.         {
  2987.             spot1 = (spot1 - (dir * 0.5));
  2988.             flr = dropline (spot1);
  2989.             if (((flr + bmaxjump) < goalheight))
  2990.             {
  2991.                 okpath = FALSE;
  2992.             }
  2993.             spot1 = (spot1 + dir);
  2994.             tests = (tests - 0.5);
  2995.             flr = dropline (spot1);
  2996.             if (((flr + bmaxjump) < goalheight))
  2997.             {
  2998.                 if (!okpath)
  2999.                 {
  3000.                     return (FALSE);
  3001.                 }
  3002.                 spot1 = (spot1 + (dir * 0.5));
  3003.                 tests = (tests - 0.5);
  3004.                 flr = dropline (spot1);
  3005.                 if (((flr + bmaxjump) < goalheight))
  3006.                 {
  3007.                     return (FALSE);
  3008.                 }
  3009.             }
  3010.         }
  3011.     }
  3012.     return (TRUE);
  3013. };
  3014. float (entity a, entity b) IsUpstream;
  3015.  
  3016. float (entity a, entity b, float truereach) Reachable =
  3017. {
  3018.     local vector spot1;
  3019.     local vector spot2;
  3020.     local vector borg;
  3021.     local float lnd;
  3022.     local float vel;
  3023.     local float diffz;
  3024.     local float diffxy;
  3025.     local float rng;
  3026.     local float maxzd;
  3027.     local float bmaxjump;
  3028.     local float brad;
  3029.     local string tmp;
  3030.  
  3031.     if (truereach)
  3032.     {
  3033.         bmaxjump = MAXJUMP;
  3034.     }
  3035.     else
  3036.     {
  3037.         bmaxjump = (0.6 * MAXJUMP);
  3038.     }
  3039.     if ((b.pathtype != DROPPED))
  3040.     {
  3041.         borg = ((b.absmin + b.absmax) * 0.5);
  3042.         borg_z = (b.absmin_z + TRUE);
  3043.     }
  3044.     else
  3045.     {
  3046.         if ((a.pathtype == DROPPED))
  3047.         {
  3048.             if (IsUpstream (a, b))
  3049.             {
  3050.                 return (TRUE);
  3051.             }
  3052.         }
  3053.         borg = b.origin;
  3054.     }
  3055.     spot1 = a.origin;
  3056.     spot2 = borg;
  3057.     if ((b.pathtype != DROPPED))
  3058.     {
  3059.         spot2_z = ((b.absmin_z + b.absmax_z) * 0.5);
  3060.     }
  3061.     rng = vlen ((spot2 - spot1));
  3062.     if (truereach)
  3063.     {
  3064.         if ((rng > SEARCH_RADIUS))
  3065.         {
  3066.             return (FALSE);
  3067.         }
  3068.     }
  3069.     else
  3070.     {
  3071.         if ((rng > (SEARCH_RADIUS - (FL_SWIM * BOTSPEED))))
  3072.         {
  3073.             return (FALSE);
  3074.         }
  3075.     }
  3076.     lnd = pointcontents (a.origin);
  3077.     if ((lnd != CONTENT_WATER))
  3078.     {
  3079.         spot1_z = ((dropline (spot1) + self.view_ofs_z) - self.mins_z);
  3080.     }
  3081.     traceline (spot1, spot2, TRUE, a);
  3082.     spot2 = borg;
  3083.     if ((lnd == CONTENT_WATER))
  3084.     {
  3085.         if (!trace_inopen)
  3086.         {
  3087.             if ((trace_fraction == TRUE))
  3088.             {
  3089.                 return (TRUE);
  3090.             }
  3091.             if (truereach)
  3092.             {
  3093.                 return (TRUE);
  3094.             }
  3095.         }
  3096.         if (truereach)
  3097.         {
  3098.             maxzd = 45;
  3099.             lnd = pointcontents ((a.origin + self.view_ofs));
  3100.             if ((lnd == CONTENT_WATER))
  3101.             {
  3102.                 maxzd = (maxzd + self.view_ofs_z);
  3103.             }
  3104.             if ((spot2_z < (a.origin_z + maxzd)))
  3105.             {
  3106.                 if ((trace_fraction == TRUE))
  3107.                 {
  3108.                     return (TRUE);
  3109.                 }
  3110.                 spot1_z = spot2_z;
  3111.                 traceline (spot1, spot2, TRUE, a);
  3112.                 if ((trace_fraction == TRUE))
  3113.                 {
  3114.                     return (TRUE);
  3115.                 }
  3116.             }
  3117.         }
  3118.     }
  3119.     if ((trace_fraction != TRUE))
  3120.     {
  3121.         return (FALSE);
  3122.     }
  3123.     spot1 = a.origin;
  3124.     if ((spot2_z > (spot1_z + bmaxjump)))
  3125.     {
  3126.         return (FALSE);
  3127.     }
  3128.     spot1 = a.origin;
  3129.     spot1_z = FALSE;
  3130.     spot2 = borg;
  3131.     spot2_z = FALSE;
  3132.     diffxy = vlen ((spot2 - spot1));
  3133.     diffxy = (diffxy - ((LEVELJUMPTIME * BOTSPEED) * MOVETYPE_BOUNCE));
  3134.     if ((diffxy < FALSE))
  3135.     {
  3136.         return (TRUE);
  3137.     }
  3138.     vel = FALSE;
  3139.     diffz = (a.origin_z - borg_z);
  3140.     while ((diffz > FALSE))
  3141.     {
  3142.         diffxy = (diffxy - BOTSPEED);
  3143.         vel = (vel - GRAVITY);
  3144.         diffz = (diffz + (0.1 * vel));
  3145.     }
  3146.     if ((diffxy < FALSE))
  3147.     {
  3148.         return (TRUE);
  3149.     }
  3150.     return (BotWalkable (a, b, bmaxjump));
  3151. };
  3152.  
  3153. void (entity a, entity b) BotReachable =
  3154. {
  3155.     return (Reachable (a, b, FALSE));
  3156. };
  3157.  
  3158. void (entity b) TrueReachable =
  3159. {
  3160.     return (Reachable (self, b, TRUE));
  3161. };
  3162.  
  3163.  
  3164. void (float dist) ai_botrun;
  3165. void () bot_chase;
  3166. void () bot_trigger1;
  3167. void () aibot_chooseGoal;
  3168. float () BotFindTarget;
  3169.  
  3170. void () shoottarget =
  3171. {
  3172.     local vector dir;
  3173.     local entity botTarget;
  3174.  
  3175.     botTarget = self.goalentity;
  3176.     bot_trigger1 ();
  3177.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", TRUE, ATTN_NORM);
  3178.     dir = ((botTarget.goalentity.absmin + botTarget.goalentity.absmax) * 0.5);
  3179.     dir = normalize ((dir - self.origin));
  3180.     FireBullets (MOVETYPE_TOSS, dir, '0.04 0.04 0');
  3181.     self.attack_finished = (time + 0.5);
  3182.     self.enemy = world;
  3183.     if ((botTarget.goalentity.classname == "door"))
  3184.     {
  3185.         self.search_time = (time + FL_CLIENT);
  3186.     }
  3187. };
  3188.  
  3189. void (float dist) ai_botseek =
  3190. {
  3191.     local entity botTarget;
  3192.     local vector dir;
  3193.     local float rng;
  3194.     local float oldrng;
  3195.  
  3196.     if (self.enemy)
  3197.     {
  3198.         aibot_setupchase ();
  3199.     }
  3200.     if (BotFindTarget ())
  3201.     {
  3202.         self.lefty = (self.lefty | FAR_SEEK);
  3203.         return;
  3204.     }
  3205.     botTarget = self.goalentity;
  3206.     if ((time < self.search_time))
  3207.     {
  3208.         if ((botTarget.goalentity.classname == "train"))
  3209.         {
  3210.             dir = ((botTarget.goalentity.absmin + botTarget.goalentity.absmax) * 0.5);
  3211.             dir_z = (botTarget.goalentity.absmax_z + TRUE);
  3212.             setorigin (botTarget, dir);
  3213.         }
  3214.         if ((botTarget.goalentity.solid != SOLID_NOT))
  3215.         {
  3216.             oldrng = vlen ((botTarget.origin - self.origin));
  3217.             Botmovetogoal (dist);
  3218.             rng = vlen ((botTarget.origin - self.origin));
  3219.             if ((rng >= oldrng))
  3220.             {
  3221.                 self.search_time = (self.search_time - 0.4);
  3222.                 if ((botTarget.goalentity == botTarget))
  3223.                 {
  3224.                 }
  3225.             }
  3226.             return;
  3227.         }
  3228.     }
  3229.     aibot_chooseGoal ();
  3230.     if ((botTarget.goalentity.takedamage == DAMAGE_YES))
  3231.     {
  3232.         shoottarget ();
  3233.     }
  3234.     Botmovetogoal (dist);
  3235. };
  3236.  
  3237. float (entity e) thingweight =
  3238. {
  3239.     local float weight;
  3240.     local float OK_HIGH;
  3241.     local float recent;
  3242.     local float waittime;
  3243.  
  3244.     weight = DONT_WANT;
  3245.     OK_HIGH = FALSE;
  3246.     if ((self.flags & FL_SWIM))
  3247.     {
  3248.         OK_HIGH = Swimto (e);
  3249.     }
  3250.     if ((e.lastbot == self))
  3251.     {
  3252.         recent = (e.lasttime > (time - FL_CLIENT));
  3253.         if (!recent)
  3254.         {
  3255.             waittime = (time - (LOOPTIME * random ()));
  3256.             recent = (e.lasttime > waittime);
  3257.         }
  3258.         if (recent)
  3259.         {
  3260.             return (DONT_WANT);
  3261.         }
  3262.     }
  3263.     if (e.th_weight)
  3264.     {
  3265.         weight = e.th_weight (e);
  3266.     }
  3267.     else
  3268.     {
  3269.         e.pathtype = NEVERTARGET;
  3270.     }
  3271.     if ((weight > DONT_WANT))
  3272.     {
  3273.         if (!OK_HIGH)
  3274.         {
  3275.             if ((e.absmin_z > (self.origin_z + MAXJUMP)))
  3276.             {
  3277.                 weight = DONT_WANT;
  3278.             }
  3279.         }
  3280.     }
  3281.     return (weight);
  3282. };
  3283.  
  3284. float (entity e) trigweight =
  3285. {
  3286.     local float weight;
  3287.  
  3288.     weight = DONT_WANT;
  3289.     if ((e.lastbot == self))
  3290.     {
  3291.         if ((e.lasttime > (time - FL_CLIENT)))
  3292.         {
  3293.             return (DONT_WANT);
  3294.         }
  3295.     }
  3296.     if (e.th_weight)
  3297.     {
  3298.         weight = e.th_weight (e);
  3299.     }
  3300.     else
  3301.     {
  3302.         e.pathtype = NEVERTARGET;
  3303.     }
  3304.     return (weight);
  3305. };
  3306.  
  3307. float (entity e) itemweight =
  3308. {
  3309.     local float weight;
  3310.     local float OK_HIGH;
  3311.  
  3312.     weight = DONT_WANT;
  3313.     OK_HIGH = FALSE;
  3314.     if ((self.flags & FL_SWIM))
  3315.     {
  3316.         OK_HIGH = Swimto (e);
  3317.     }
  3318.     if ((e.lastbot == self))
  3319.     {
  3320.         if ((e.lasttime > (time - MOVETYPE_FLY)))
  3321.         {
  3322.             return (DONT_WANT);
  3323.         }
  3324.     }
  3325.     if (e.th_weight)
  3326.     {
  3327.         weight = e.th_weight (e);
  3328.     }
  3329.     else
  3330.     {
  3331.         e.pathtype = NEVERTARGET;
  3332.     }
  3333.     if ((weight > DONT_WANT))
  3334.     {
  3335.         if (!OK_HIGH)
  3336.         {
  3337.             if ((e.absmin_z > (self.origin_z + MAXJUMP)))
  3338.             {
  3339.                 weight = DONT_WANT;
  3340.             }
  3341.         }
  3342.     }
  3343.     if ((weight > DONT_WANT))
  3344.     {
  3345.         if (!TrueReachable (e))
  3346.         {
  3347.             weight = DONT_WANT;
  3348.         }
  3349.     }
  3350.     return (weight);
  3351. };
  3352.  
  3353. vector (float n) chooseRoamTarget =
  3354. {
  3355.     local float len;
  3356.     local float r;
  3357.     local float d;
  3358.     local float m;
  3359.     local float lnd;
  3360.     local vector dir;
  3361.     local vector below;
  3362.     local vector bestorg;
  3363.  
  3364.     bestorg = self.origin;
  3365.     d = random ();
  3366.     if ((d < 0.8))
  3367.     {
  3368.         r = random ();
  3369.         m = TRUE;
  3370.         if ((r < 0.5))
  3371.         {
  3372.             m = CONTENT_EMPTY;
  3373.         }
  3374.         bestorg_x = (bestorg_x + (m * ((700 * random ()) + 50)));
  3375.     }
  3376.     if ((d > 0.2))
  3377.     {
  3378.         r = random ();
  3379.         m = TRUE;
  3380.         if ((r < 0.5))
  3381.         {
  3382.             m = CONTENT_EMPTY;
  3383.         }
  3384.         bestorg_y = (bestorg_y + (m * ((700 * random ()) + 50)));
  3385.     }
  3386.     bestorg_z = (((bestorg_z + ((MOVETYPE_WALK * MAXJUMP) * random ())) - (FL_SWIM * MAXJUMP)) - TRUE);
  3387.     traceline (self.origin, bestorg, TRUE, self);
  3388.     dir = normalize ((bestorg - self.origin));
  3389.     len = vlen ((bestorg - self.origin));
  3390.     bestorg = (self.origin + (dir * ((len * trace_fraction) - KINDA_WANT)));
  3391.     below = bestorg;
  3392.     below_z = (dropline (below) + TRUE);
  3393.     lnd = pointcontents (below);
  3394.     if ((lnd != CONTENT_EMPTY))
  3395.     {
  3396.         if ((lnd != CONTENT_WATER))
  3397.         {
  3398.             if ((n < MOVETYPE_PUSH))
  3399.             {
  3400.                 return (chooseRoamTarget ((n + TRUE)));
  3401.             }
  3402.         }
  3403.     }
  3404.     below = (bestorg - (SVC_INTERMISSION * dir));
  3405.     below_z = (dropline (below) + TRUE);
  3406.     lnd = pointcontents (below);
  3407.     if ((lnd != CONTENT_EMPTY))
  3408.     {
  3409.         if ((lnd != CONTENT_WATER))
  3410.         {
  3411.             if ((n < MOVETYPE_PUSH))
  3412.             {
  3413.                 return (chooseRoamTarget ((n + TRUE)));
  3414.             }
  3415.         }
  3416.     }
  3417.     r = (n + (random () * MOVETYPE_WALK));
  3418.     if (((bestorg_z > self.origin_z) || (r > MOVETYPE_FLY)))
  3419.     {
  3420.         bestorg_z = (below_z - self.mins_z);
  3421.     }
  3422.     len = vlen ((bestorg - self.origin));
  3423.     if ((len < KINDA_WANT))
  3424.     {
  3425.         if ((n < MOVETYPE_PUSH))
  3426.         {
  3427.             return (chooseRoamTarget ((n + TRUE)));
  3428.         }
  3429.     }
  3430.     return (bestorg);
  3431. };
  3432.  
  3433. float (entity e) cacheweight =
  3434. {
  3435.     local float weight;
  3436.     local float tw;
  3437.     local float dis;
  3438.     local float it;
  3439.  
  3440.     weight = FALSE;
  3441.     if ((e.lastbot == self))
  3442.     {
  3443.         if ((e.lasttime > (time - FL_SWIM)))
  3444.         {
  3445.             return (weight);
  3446.         }
  3447.     }
  3448.     dis = vlen ((self.origin - e.origin));
  3449.     it = self.items;
  3450.     e.pendingcache = world;
  3451.     e.pendinglen = FALSE;
  3452.     if (e.rocketcache)
  3453.     {
  3454.         if (((e.rocketcache.solid == SOLID_TRIGGER) || (e.rocketcache.nextthink < (time + MOVETYPE_STEP))))
  3455.         {
  3456.             if (((self.rocketcache != e.rocketcache) || (self.rocketlen > e.rocketlen)))
  3457.             {
  3458.                 weight = ((1000000 - e.rocketlen) - (FL_SWIM * dis));
  3459.                 if ((it & IT_ROCKET_LAUNCHER))
  3460.                 {
  3461.                     weight = (weight * 0.5);
  3462.                 }
  3463.                 e.pendingcache = e.rocketcache;
  3464.                 e.pendinglen = e.rocketlen;
  3465.             }
  3466.         }
  3467.     }
  3468.     if (e.lightningcache)
  3469.     {
  3470.         if (((e.lightningcache.solid == SOLID_TRIGGER) || (e.lightningcache.nextthink < (time + MOVETYPE_STEP))))
  3471.         {
  3472.             if (((self.lightningcache != e.lightningcache) || (self.lightninglen > e.lightninglen)))
  3473.             {
  3474.                 tw = ((1000000 - e.lightninglen) - (FL_SWIM * dis));
  3475.                 if ((it & IT_LIGHTNING))
  3476.                 {
  3477.                     tw = (tw * 0.5);
  3478.                 }
  3479.                 if ((tw > weight))
  3480.                 {
  3481.                     weight = tw;
  3482.                     e.pendingcache = e.lightningcache;
  3483.                     e.pendinglen = e.lightninglen;
  3484.                 }
  3485.             }
  3486.         }
  3487.     }
  3488.     if ((self.armorvalue < 101))
  3489.     {
  3490.         if (e.armorcache)
  3491.         {
  3492.             if (((e.armorcache.solid == SOLID_TRIGGER) || (e.armorcache.nextthink < (time + MOVETYPE_STEP))))
  3493.             {
  3494.                 if (((self.armorcache != e.armorcache) || (self.armorlen > e.armorlen)))
  3495.                 {
  3496.                     tw = ((1000000 - e.armorlen) - (FL_SWIM * dis));
  3497.                     if ((tw > weight))
  3498.                     {
  3499.                         weight = tw;
  3500.                         e.pendingcache = e.armorcache;
  3501.                         e.pendinglen = e.armorlen;
  3502.                     }
  3503.                 }
  3504.             }
  3505.         }
  3506.     }
  3507.     if (e.nailcache)
  3508.     {
  3509.         if (((e.nailcache.solid == SOLID_TRIGGER) || (e.nailcache.nextthink < (time + FL_SWIM))))
  3510.         {
  3511.             if (((self.nailcache != e.nailcache) || (self.naillen > e.naillen)))
  3512.             {
  3513.                 tw = ((1000000 - e.naillen) - (FL_SWIM * dis));
  3514.                 if ((it & IT_SUPER_NAILGUN))
  3515.                 {
  3516.                     tw = (tw * 0.5);
  3517.                 }
  3518.                 if ((tw > (weight + 2500)))
  3519.                 {
  3520.                     weight = tw;
  3521.                     e.pendingcache = e.nailcache;
  3522.                     e.pendinglen = e.naillen;
  3523.                 }
  3524.             }
  3525.         }
  3526.     }
  3527.     if (e.grenadecache)
  3528.     {
  3529.         if (((e.grenadecache.solid == SOLID_TRIGGER) || (e.grenadecache.nextthink < (time + FL_SWIM))))
  3530.         {
  3531.             if (((self.grenadecache != e.grenadecache) || (self.grenadelen > e.grenadelen)))
  3532.             {
  3533.                 tw = ((1000000 - e.grenadelen) - (FL_SWIM * dis));
  3534.                 if ((it & IT_GRENADE_LAUNCHER))
  3535.                 {
  3536.                     tw = (tw * 0.5);
  3537.                 }
  3538.                 if ((tw > (weight + 2500)))
  3539.                 {
  3540.                     weight = tw;
  3541.                     e.pendingcache = e.grenadecache;
  3542.                     e.pendinglen = e.grenadelen;
  3543.                 }
  3544.             }
  3545.         }
  3546.     }
  3547.     if (e.powerupcache)
  3548.     {
  3549.         if ((e.powerupcache.solid == SOLID_TRIGGER))
  3550.         {
  3551.             if (((self.powerupcache != e.powerupcache) || (self.poweruplen > e.poweruplen)))
  3552.             {
  3553.                 tw = ((1000000 - e.poweruplen) - (FL_SWIM * dis));
  3554.                 if ((tw > weight))
  3555.                 {
  3556.                     weight = tw;
  3557.                     e.pendingcache = e.powerupcache;
  3558.                     e.pendinglen = e.poweruplen;
  3559.                 }
  3560.             }
  3561.         }
  3562.     }
  3563.     return (weight);
  3564. };
  3565.  
  3566. float (entity e) pathweight =
  3567. {
  3568.     local float OK_HIGH;
  3569.     local float weight;
  3570.     local vector org;
  3571.  
  3572.     weight = DONT_WANT;
  3573.     if (TrueReachable (e))
  3574.     {
  3575.         weight = cacheweight (e);
  3576.         if ((weight > FALSE))
  3577.         {
  3578.             return (weight);
  3579.         }
  3580.         weight = vlen ((self.origin - org));
  3581.         weight = ((50 * SEARCH_RADIUS) - weight);
  3582.         if ((e.lastbot == self))
  3583.         {
  3584.             if ((e.lasttime > (time - MOVETYPE_TOSS)))
  3585.             {
  3586.                 weight = DONT_WANT;
  3587.             }
  3588.             else
  3589.             {
  3590.                 if ((e.lasttime > (time - LOOPTIME)))
  3591.                 {
  3592.                     weight = ((weight - (FL_SWIM * SEARCH_RADIUS)) - (((45 * SEARCH_RADIUS) * ((LOOPTIME + e.lasttime) - time)) / LOOPTIME));
  3593.                 }
  3594.             }
  3595.         }
  3596.         else
  3597.         {
  3598.             if (teamplay)
  3599.             {
  3600.                 if ((e.lastbot.team == self.team))
  3601.                 {
  3602.                     if ((e.lasttime > (time - 1.2)))
  3603.                     {
  3604.                         weight = DONT_WANT;
  3605.                     }
  3606.                     else
  3607.                     {
  3608.                         if ((e.lasttime > (time - FL_SWIM)))
  3609.                         {
  3610.                             weight = (weight - SEARCH_RADIUS);
  3611.                         }
  3612.                     }
  3613.                 }
  3614.             }
  3615.         }
  3616.     }
  3617.     return (weight);
  3618. };
  3619.  
  3620. void () goForAir =
  3621. {
  3622.     local vector bestorg;
  3623.     local entity botTarget;
  3624.  
  3625.     if (VERBOSEBOT)
  3626.     {
  3627.         dprint (self.teamname);
  3628.         dprint (self.netname);
  3629.         dprint (" needs air!\n");
  3630.     }
  3631.     bestorg = self.origin;
  3632.     bestorg_z = (bestorg_z + 800);
  3633.     traceline (self.origin, bestorg, TRUE, self);
  3634.     if (!trace_inopen)
  3635.     {
  3636.         bestorg = chooseRoamTarget (TRUE);
  3637.         bestorg_z = (bestorg_z + 200);
  3638.     }
  3639.     botTarget = self.goalentity;
  3640.     botTarget.goalentity = botTarget;
  3641.     if ((self.goalentity.classname != "BotTarget"))
  3642.     {
  3643.         objerror ("bad bot target in botgoal! 1\n");
  3644.     }
  3645.     setorigin (botTarget, bestorg);
  3646. };
  3647.  
  3648. void (entity item) ageCache =
  3649. {
  3650.     if (self.rocketcache)
  3651.     {
  3652.         self.rocketlen = (self.rocketlen + TRUE);
  3653.     }
  3654.     if (self.lightningcache)
  3655.     {
  3656.         self.lightninglen = (self.lightninglen + TRUE);
  3657.     }
  3658.     if (self.armorcache)
  3659.     {
  3660.         self.armorlen = (self.armorlen + TRUE);
  3661.     }
  3662.     if (self.powerupcache)
  3663.     {
  3664.         self.poweruplen = (self.poweruplen + TRUE);
  3665.     }
  3666.     if (self.nailcache)
  3667.     {
  3668.         self.naillen = (self.naillen + TRUE);
  3669.     }
  3670.     if (self.grenadecache)
  3671.     {
  3672.         self.grenadelen = (self.grenadelen + TRUE);
  3673.     }
  3674.     if ((item.solid == SOLID_TRIGGER))
  3675.     {
  3676.         if ((self.rocketcache == item))
  3677.         {
  3678.             self.rocketlen = TRUE;
  3679.         }
  3680.         else
  3681.         {
  3682.             if ((self.lightningcache == item))
  3683.             {
  3684.                 self.lightninglen = TRUE;
  3685.             }
  3686.             else
  3687.             {
  3688.                 if ((self.armorcache == item))
  3689.                 {
  3690.                     self.armorlen = TRUE;
  3691.                 }
  3692.                 else
  3693.                 {
  3694.                     if ((self.powerupcache == item))
  3695.                     {
  3696.                         self.poweruplen = TRUE;
  3697.                     }
  3698.                     else
  3699.                     {
  3700.                         if ((self.nailcache == item))
  3701.                         {
  3702.                             self.naillen = TRUE;
  3703.                         }
  3704.                         else
  3705.                         {
  3706.                             if ((self.grenadecache == item))
  3707.                             {
  3708.                                 self.grenadelen = TRUE;
  3709.                             }
  3710.                         }
  3711.                     }
  3712.                 }
  3713.             }
  3714.         }
  3715.     }
  3716. };
  3717.  
  3718. void () resetCache =
  3719. {
  3720.     self.pendingcache = world;
  3721.     self.pendinglen = FALSE;
  3722.     if (self.rocketcache)
  3723.     {
  3724.         if ((self.rocketcache.solid == SOLID_NOT))
  3725.         {
  3726.             self.rocketcache = world;
  3727.             self.rocketlen = FALSE;
  3728.         }
  3729.     }
  3730.     if (self.lightningcache)
  3731.     {
  3732.         if ((self.lightningcache.solid == SOLID_NOT))
  3733.         {
  3734.             self.lightningcache = world;
  3735.             self.lightninglen = FALSE;
  3736.         }
  3737.     }
  3738.     if (self.armorcache)
  3739.     {
  3740.         if ((self.armorcache.solid == SOLID_NOT))
  3741.         {
  3742.             self.armorcache = world;
  3743.             self.armorlen = FALSE;
  3744.         }
  3745.     }
  3746.     if (self.powerupcache)
  3747.     {
  3748.         if ((self.powerupcache.solid == SOLID_NOT))
  3749.         {
  3750.             self.powerupcache = world;
  3751.             self.poweruplen = FALSE;
  3752.         }
  3753.     }
  3754.     if (self.nailcache)
  3755.     {
  3756.         if ((self.nailcache.solid == SOLID_NOT))
  3757.         {
  3758.             self.nailcache = world;
  3759.             self.naillen = FALSE;
  3760.         }
  3761.     }
  3762.     if (self.grenadecache)
  3763.     {
  3764.         if ((self.grenadecache.solid == SOLID_NOT))
  3765.         {
  3766.             self.grenadecache = world;
  3767.             self.grenadelen = FALSE;
  3768.         }
  3769.     }
  3770. };
  3771.  
  3772. void () updateBotCache =
  3773. {
  3774.     if (self.pendingcache.th_update)
  3775.     {
  3776.         self.pendingcache.th_update ();
  3777.     }
  3778.     else
  3779.     {
  3780.         dprint ("Error - no think update for ");
  3781.         dprint (self.pendingcache.classname);
  3782.         dprint ("\n");
  3783.     }
  3784.     self.pendingcache = world;
  3785.     self.pendinglen = FALSE;
  3786. };
  3787.  
  3788. void () aibot_chooseGoal =
  3789. {
  3790.     local vector org;
  3791.     local vector bestorg;
  3792.     local float best;
  3793.     local float weight;
  3794.     local float d1;
  3795.     local float d2;
  3796.     local float OK_NOTVIS;
  3797.     local entity e;
  3798.     local entity current;
  3799.     local entity botTarget;
  3800.     local string tmp;
  3801.  
  3802.     botTarget = self.goalentity;
  3803.     if ((self.lefty & FAR_SEEK))
  3804.     {
  3805.         self.lefty = ((self.lefty - (self.lefty & LOCAL_TIME)) - FAR_SEEK);
  3806.     }
  3807.     if ((self.lefty & ONTRAIN))
  3808.     {
  3809.         self.lefty = (self.lefty - ONTRAIN);
  3810.     }
  3811.     self.lefty = (self.lefty + TRUE);
  3812.     current = botTarget.goalentity;
  3813.     self.search_time = (time + MOVETYPE_STEP);
  3814.     best = DONT_WANT;
  3815.     OK_NOTVIS = FALSE;
  3816.     if ((self.air_finished < (time + MOVETYPE_FLYMISSILE)))
  3817.     {
  3818.         goForAir ();
  3819.         return;
  3820.     }
  3821.     if (((self.lefty & LOCAL_TIME) < MOVETYPE_FLY))
  3822.     {
  3823.         e = findradius (self.origin, SEARCH_RADIUS);
  3824.         while (e)
  3825.         {
  3826.             weight = DONT_WANT;
  3827.             if ((e == current))
  3828.             {
  3829.                 weight = DONT_WANT;
  3830.             }
  3831.             else
  3832.             {
  3833.                 if (e.pathtype)
  3834.                 {
  3835.                     weight = DONT_WANT;
  3836.                 }
  3837.                 else
  3838.                 {
  3839.                     if ((e.solid == SOLID_NOT))
  3840.                     {
  3841.                         weight = DONT_WANT;
  3842.                     }
  3843.                     else
  3844.                     {
  3845.                         if ((e.solid == SOLID_TRIGGER))
  3846.                         {
  3847.                             if (e.istrigger)
  3848.                             {
  3849.                                 weight = trigweight (e);
  3850.                             }
  3851.                             else
  3852.                             {
  3853.                                 weight = itemweight (e);
  3854.                             }
  3855.                         }
  3856.                         else
  3857.                         {
  3858.                             weight = thingweight (e);
  3859.                         }
  3860.                     }
  3861.                 }
  3862.             }
  3863.             if ((weight > (KINDA_WANT - MOVETYPE_FLY)))
  3864.             {
  3865.                 if ((weight < (WANT + FL_SWIM)))
  3866.                 {
  3867.                     if (((e.absmin_z + MAXJUMP) < self.absmin_z))
  3868.                     {
  3869.                         weight = (KINDA_WANT - MOVETYPE_FLY);
  3870.                     }
  3871.                 }
  3872.             }
  3873.             if ((weight > DONT_WANT))
  3874.             {
  3875.                 org = ((e.absmin + e.absmax) * 0.5);
  3876.                 org_z = (e.absmin_z + TRUE);
  3877.                 if ((((e.classname == "plat") || (e.classname == "func_plat")) || (e.classname == "train")))
  3878.                 {
  3879.                     org_z = (e.absmax_z + TRUE);
  3880.                 }
  3881.                 if ((weight == best))
  3882.                 {
  3883.                     d1 = vlen ((self.origin - bestorg));
  3884.                     d2 = vlen ((self.origin - org));
  3885.                     weight = ((weight + (random () * MOVETYPE_FLY)) - FL_SWIM);
  3886.                     if ((d1 < d2))
  3887.                     {
  3888.                         weight = (weight - TRUE);
  3889.                     }
  3890.                     if ((weight > best))
  3891.                     {
  3892.                         weight = best;
  3893.                         best = (best - TRUE);
  3894.                     }
  3895.                 }
  3896.                 if ((weight > best))
  3897.                 {
  3898.                     botTarget.goalentity = e;
  3899.                     best = weight;
  3900.                     bestorg = org;
  3901.                 }
  3902.             }
  3903.             e = e.chain;
  3904.         }
  3905.     }
  3906.     resetCache ();
  3907.     if ((best < (KINDA_WANT - MOVETYPE_WALK)))
  3908.     {
  3909.         if ((best > DONT_WANT))
  3910.         {
  3911.             best = (1000000 - 900);
  3912.         }
  3913.         e = findradius (self.origin, SEARCH_RADIUS);
  3914.         best = DONT_WANT;
  3915.         while (e)
  3916.         {
  3917.             if (((e.pathtype == DROPPED) || (e.pathtype == TELEPORT)))
  3918.             {
  3919.                 if ((e == current))
  3920.                 {
  3921.                     weight = DONT_WANT;
  3922.                 }
  3923.                 else
  3924.                 {
  3925.                     weight = pathweight (e);
  3926.                 }
  3927.                 if ((weight > best))
  3928.                 {
  3929.                     best = weight;
  3930.                     botTarget.goalentity = e;
  3931.                     self.pendingcache = e.pendingcache;
  3932.                     self.pendinglen = e.pendinglen;
  3933.                     bestorg = e.origin;
  3934.                     if (!bestorg)
  3935.                     {
  3936.                         bestorg = ((e.absmin + e.absmax) * 0.5);
  3937.                         bestorg_z = (e.absmin_z + TRUE);
  3938.                     }
  3939.                     self.lefty = (self.lefty | FAR_SEEK);
  3940.                 }
  3941.             }
  3942.             e = e.chain;
  3943.         }
  3944.     }
  3945.     if ((best > DONT_WANT))
  3946.     {
  3947.         if (self.pendingcache)
  3948.         {
  3949.             updateBotCache ();
  3950.         }
  3951.         else
  3952.         {
  3953.             if ((botTarget.goalentity.classname != "BotPath"))
  3954.             {
  3955.                 ageCache (botTarget.goalentity);
  3956.             }
  3957.         }
  3958.     }
  3959.     if ((best <= DONT_WANT))
  3960.     {
  3961.         botTarget.goalentity = botTarget;
  3962.         bestorg = chooseRoamTarget (FALSE);
  3963.         self.lefty = (self.lefty | FAR_SEEK);
  3964.         self.search_time = (time + FL_SWIM);
  3965.     }
  3966.     if (VERBOSEBOT)
  3967.     {
  3968.         dprint (self.teamname);
  3969.         dprint (self.netname);
  3970.         dprint (" going after ");
  3971.         dprint (botTarget.goalentity.classname);
  3972.         dprint ("\n");
  3973.     }
  3974.     if (botTarget.goalentity)
  3975.     {
  3976.         if ((botTarget.goalentity != botTarget))
  3977.         {
  3978.             botTarget.goalentity.lastbot = self;
  3979.             botTarget.goalentity.lasttime = time;
  3980.         }
  3981.     }
  3982.     if ((botTarget.goalentity.classname == "func_button"))
  3983.     {
  3984.         bestorg = ((bestorg - botTarget.goalentity.pos2) - (FL_MONSTER * normalize (botTarget.goalentity.pos2)));
  3985.     }
  3986.     if ((botTarget.classname != "BotTarget"))
  3987.     {
  3988.         objerror ("bad bot target in botgoal! 2\n");
  3989.     }
  3990.     setorigin (botTarget, bestorg);
  3991. };
  3992.  
  3993. float (entity e) RunAwayWeight =
  3994. {
  3995.     local float weight;
  3996.  
  3997.     if (!TrueReachable (e))
  3998.     {
  3999.         return (FALSE);
  4000.     }
  4001.     traceline ((self.enemy.origin + self.enemy.view_ofs), e.origin, TRUE, self.enemy);
  4002.     if ((trace_fraction != TRUE))
  4003.     {
  4004.         weight = WANT;
  4005.     }
  4006.     if ((trace_inopen && trace_inwater))
  4007.     {
  4008.         weight = (WANT - MOVETYPE_FLY);
  4009.     }
  4010.     weight = (weight + (0.1 * vlen ((self.enemy.origin - e.origin))));
  4011.     weight = (weight + (KINDA_WANT * random ()));
  4012.     return (weight);
  4013. };
  4014. void (entity en) RouteToEnemy;
  4015.  
  4016. entity (entity chaser, entity en) BestChaseRoute =
  4017. {
  4018.     local entity e;
  4019.     local entity p;
  4020.     local entity tmp;
  4021.     local float weight;
  4022.     local float best;
  4023.     local string ts;
  4024.  
  4025.     RouteToEnemy (en);
  4026.     e = findradius (chaser.origin, SEARCH_RADIUS);
  4027.     best = 1000000;
  4028.     p = en;
  4029.     tmp = self;
  4030.     self = chaser;
  4031.     while (e)
  4032.     {
  4033.         if (((e.pathtype == DROPPED) || (e.pathtype == TELEPORT)))
  4034.         {
  4035.             weight = 1000000;
  4036.             if ((e.enemycache == en))
  4037.             {
  4038.                 if (TrueReachable (e))
  4039.                 {
  4040.                     weight = (e.enemylen + (vlen ((self.origin - e.origin)) * 0.5));
  4041.                 }
  4042.             }
  4043.             if ((weight < best))
  4044.             {
  4045.                 best = weight;
  4046.                 p = e;
  4047.             }
  4048.         }
  4049.         e = e.chain;
  4050.     }
  4051.     self = tmp;
  4052.     return (p);
  4053. };
  4054.  
  4055.  
  4056. void () endEnemy =
  4057. {
  4058.     local entity olden;
  4059.  
  4060.     olden = self.enemy;
  4061.     if ((self.lefty & GETGOODY))
  4062.     {
  4063.         self.lefty = (self.lefty - GETGOODY);
  4064.     }
  4065.     if ((self.lefty & MULTIENEMY))
  4066.     {
  4067.         self.lefty = (self.lefty - MULTIENEMY);
  4068.     }
  4069.     self.enemy = world;
  4070.     self.think = self.th_walk;
  4071.     self.nextthink = (time + 0.1);
  4072.     self.search_time = (time - TRUE);
  4073.     self.enemyrun = FALSE;
  4074.     self.goalentity.goalentity = self.goalentity;
  4075.     if ((olden.classname == "player"))
  4076.     {
  4077.         if ((olden.enemy == self))
  4078.         {
  4079.             olden.enemy = world;
  4080.         }
  4081.     }
  4082. };
  4083.  
  4084. void () CallForHelp =
  4085. {
  4086.     local entity e;
  4087.     local entity p;
  4088.     local entity tmp;
  4089.     local float d;
  4090.  
  4091.     HELPING = TRUE;
  4092.     e = find (world, classname, "dmbot");
  4093.     while (e)
  4094.     {
  4095.         if ((e != self))
  4096.         {
  4097.             if ((e.team == self.team))
  4098.             {
  4099.                 if ((e.enemy == world))
  4100.                 {
  4101.                     if ((e.health > 80))
  4102.                     {
  4103.                         if ((e.items & ((((IT_ROCKET_LAUNCHER + IT_LIGHTNING) + IT_SUPER_NAILGUN) + IT_SUPER_SHOTGUN) + IT_GRENADE_LAUNCHER)))
  4104.                         {
  4105.                             p = BestChaseRoute (e, self.enemy);
  4106.                             traceline (e.origin, self.enemy.origin, TRUE, e);
  4107.                             if (((trace_fraction == TRUE) || (p.enemycache == self.enemy)))
  4108.                             {
  4109.                                 if (VERBOSEBOT)
  4110.                                 {
  4111.                                     dprint (e.teamname);
  4112.                                     dprint (e.netname);
  4113.                                     dprint (" coming to help!\n");
  4114.                                 }
  4115.                                 e.enemy = self.enemy;
  4116.                                 tmp = self;
  4117.                                 self = e;
  4118.                                 BotFoundTarget ();
  4119.                                 if ((self.goalentity.classname != "BotTarget"))
  4120.                                 {
  4121.                                     objerror ("bad bot target in bot_ai! 1\n");
  4122.                                 }
  4123.                                 setorigin (self.goalentity, p.origin);
  4124.                                 self = tmp;
  4125.                             }
  4126.                         }
  4127.                     }
  4128.                 }
  4129.             }
  4130.         }
  4131.         e = find (e, classname, "dmbot");
  4132.     }
  4133.     HELPING = FALSE;
  4134. };
  4135.  
  4136. float () RunAway =
  4137. {
  4138.     local float weap;
  4139.  
  4140.     if ((self.items & IT_INVULNERABILITY))
  4141.     {
  4142.         return (FALSE);
  4143.     }
  4144.     if ((self.enemy.items & IT_INVULNERABILITY))
  4145.     {
  4146.         return (TRUE);
  4147.     }
  4148.     if ((self.enemy.health < WANT))
  4149.     {
  4150.         return (FALSE);
  4151.     }
  4152.     weap = W_BestHeldWeapon ();
  4153.     if ((weap & (IT_ROCKET_LAUNCHER + IT_LIGHTNING)))
  4154.     {
  4155.         return (FALSE);
  4156.     }
  4157.     if ((self.items & IT_QUAD))
  4158.     {
  4159.         if (((self.health + (self.armorvalue * self.armortype)) > 50))
  4160.         {
  4161.             return (FALSE);
  4162.         }
  4163.     }
  4164.     if ((self.health < 45))
  4165.     {
  4166.         return (TRUE);
  4167.     }
  4168.     if ((weap & ((IT_SHOTGUN + IT_AXE) + IT_NAILGUN)))
  4169.     {
  4170.         if ((self.enemy.items & IT_QUAD))
  4171.         {
  4172.             return (TRUE);
  4173.         }
  4174.         if ((self.enemy.weapon & ((IT_ROCKET_LAUNCHER + IT_LIGHTNING) + IT_SUPER_NAILGUN)))
  4175.         {
  4176.             return (TRUE);
  4177.         }
  4178.     }
  4179.     if ((self.lefty & MULTIENEMY))
  4180.     {
  4181.         if ((self.health < 70))
  4182.         {
  4183.             return (TRUE);
  4184.         }
  4185.     }
  4186.     return (FALSE);
  4187. };
  4188.  
  4189. void () BotHuntTarget =
  4190. {
  4191.     if (VERBOSEBOT)
  4192.     {
  4193.         dprint (self.teamname);
  4194.         dprint (self.netname);
  4195.         dprint (": Go kick ");
  4196.         dprint (self.enemy.teamname);
  4197.         dprint (self.enemy.netname);
  4198.         dprint ("'s ass!\n");
  4199.     }
  4200.     self.enemyrun = FALSE;
  4201.     self.strafetime = FALSE;
  4202.     if ((self.lefty & ONTRAIN))
  4203.     {
  4204.         self.lefty = (self.lefty - ONTRAIN);
  4205.     }
  4206.     self.goalentity.goalentity = self.enemy;
  4207.     if ((self.enemy.enemy == world))
  4208.     {
  4209.         self.enemy.enemy = self;
  4210.     }
  4211.     if ((self.goalentity.classname != "BotTarget"))
  4212.     {
  4213.         objerror ("bad bot target in bot_ai! 2\n");
  4214.     }
  4215.     setorigin (self.goalentity, self.enemy.origin);
  4216.     self.think = self.th_run;
  4217.     self.strafeonly = FALSE;
  4218.     self.ideal_yaw = vectoyaw ((self.enemy.origin - self.origin));
  4219.     self.lefty = ((self.lefty - (self.lefty & LOCAL_TIME)) + MOVETYPE_TOSS);
  4220.     self.nextthink = (time + 0.1);
  4221.     self.attack_finished = ((time + 0.7) - (0.2 * self.skil));
  4222.     self.search_time = (time + MOVETYPE_PUSH);
  4223.     clearCache (self);
  4224.     if (teamplay)
  4225.     {
  4226.         if (!HELPING)
  4227.         {
  4228.             CallForHelp ();
  4229.         }
  4230.     }
  4231. };
  4232.  
  4233. float () BotFoundTarget =
  4234. {
  4235.     if ((self.enemy == world))
  4236.     {
  4237.         return (FALSE);
  4238.     }
  4239.     if (teamplay)
  4240.     {
  4241.         if ((self.enemy.team == self.team))
  4242.         {
  4243.             self.enemy = world;
  4244.             return (FALSE);
  4245.         }
  4246.     }
  4247.     if ((self.deadflag != DEAD_NO))
  4248.     {
  4249.         self.enemy = world;
  4250.         return (FALSE);
  4251.     }
  4252.     if ((self.enemy.deadflag != DEAD_NO))
  4253.     {
  4254.         self.enemy = world;
  4255.         return (FALSE);
  4256.     }
  4257.     if (((self.enemy.classname != "player") && (self.enemy.classname != "dmbot")))
  4258.     {
  4259.         self.enemy = world;
  4260.         return (FALSE);
  4261.     }
  4262.     if ((self.enemy == self))
  4263.     {
  4264.         self.enemy = world;
  4265.         return (FALSE);
  4266.     }
  4267.     BotHuntTarget ();
  4268.     return (TRUE);
  4269. };
  4270.  
  4271. void (entity en2) secondEnemy =
  4272. {
  4273.     if ((self.enemy.classname != "player"))
  4274.     {
  4275.         if ((en2.classname == "player"))
  4276.         {
  4277.             endEnemy ();
  4278.             self.enemy = en2;
  4279.             BotFoundTarget ();
  4280.             return;
  4281.         }
  4282.     }
  4283.     if (!enemyvisible (self.enemy))
  4284.     {
  4285.         endEnemy ();
  4286.         self.enemy = en2;
  4287.         BotFoundTarget ();
  4288.     }
  4289.     if ((en2.weapon & (IT_LIGHTNING + IT_ROCKET_LAUNCHER)))
  4290.     {
  4291.         if (!(self.enemy.weapon & (IT_LIGHTNING + IT_ROCKET_LAUNCHER)))
  4292.         {
  4293.             endEnemy ();
  4294.             self.enemy = en2;
  4295.             BotFoundTarget ();
  4296.         }
  4297.     }
  4298. };
  4299.  
  4300. float () BotfindBot =
  4301. {
  4302.     local float n;
  4303.     local entity bots;
  4304.  
  4305.     if (!self.lastbot)
  4306.     {
  4307.         self.lastbot = find (world, classname, "dmbot");
  4308.     }
  4309.     n = MOVETYPE_STEP;
  4310.     while ((n > FALSE))
  4311.     {
  4312.         n = (n - TRUE);
  4313.         bots = self.lastbot;
  4314.         if ((!teamplay || (self.team != bots.team)))
  4315.         {
  4316.             if ((bots != self))
  4317.             {
  4318.                 if ((bots != self.enemy))
  4319.                 {
  4320.                     if (visible (bots))
  4321.                     {
  4322.                         if ((bots.health > FALSE))
  4323.                         {
  4324.                             self.enemy = bots;
  4325.                             return (BotFoundTarget ());
  4326.                         }
  4327.                     }
  4328.                 }
  4329.             }
  4330.         }
  4331.         self.lastbot = find (bots, classname, "dmbot");
  4332.         if (!self.lastbot)
  4333.         {
  4334.             self.lastbot = find (world, classname, "dmbot");
  4335.         }
  4336.     }
  4337.     return (FALSE);
  4338. };
  4339.  
  4340. float () BotFindTarget =
  4341. {
  4342.     local entity client;
  4343.     local float len;
  4344.     local float bw;
  4345.  
  4346.     client = checkclient ();
  4347.     if (!client)
  4348.     {
  4349.         return (BotfindBot ());
  4350.     }
  4351.     if ((client.classname == "peeper"))
  4352.     {
  4353.         return (BotfindBot ());
  4354.     }
  4355.     if ((client == self.enemy))
  4356.     {
  4357.         return (FALSE);
  4358.     }
  4359.     if (teamplay)
  4360.     {
  4361.         if ((self.team == client.team))
  4362.         {
  4363.             return (BotfindBot ());
  4364.         }
  4365.     }
  4366.     if ((client.flags & FL_NOTARGET))
  4367.     {
  4368.         return (BotfindBot ());
  4369.     }
  4370.     if (!enemyvisible (client))
  4371.     {
  4372.         return (BotfindBot ());
  4373.     }
  4374.     if (!infrontofbot (client))
  4375.     {
  4376.         if (!hearnoise (client))
  4377.         {
  4378.             return (BotfindBot ());
  4379.         }
  4380.     }
  4381.     if (((self.origin_z > (client.origin_z + 120)) || ((self.origin_z + 120) < client.origin_z)))
  4382.     {
  4383.         self.enemy = client;
  4384.         if (RunAway ())
  4385.         {
  4386.             self.enemy = world;
  4387.             return (BotfindBot ());
  4388.         }
  4389.     }
  4390.     if ((client.items & IT_INVISIBILITY))
  4391.     {
  4392.         return (BotfindBot ());
  4393.     }
  4394.     if ((self.skil < TRUE))
  4395.     {
  4396.         len = (random () * MUST_HAVE);
  4397.         if ((len > 25))
  4398.         {
  4399.             return (FALSE);
  4400.         }
  4401.     }
  4402.     self.enemy = client;
  4403.     return (BotFoundTarget ());
  4404. };
  4405.  
  4406. void () ai_botstand =
  4407. {
  4408.     if (BotFindTarget ())
  4409.     {
  4410.         return;
  4411.     }
  4412. };
  4413.  
  4414. void () ai_botturn =
  4415. {
  4416.     if (BotFindTarget ())
  4417.     {
  4418.         return;
  4419.     }
  4420.     ChangeYaw ();
  4421. };
  4422.  
  4423. void () aibot_run_melee =
  4424. {
  4425.     self.ideal_yaw = vectoyaw ((self.enemy.origin - self.origin));
  4426.     ChangeYaw ();
  4427.     if (FacingIdeal ())
  4428.     {
  4429.         self.attack_state = AS_STRAIGHT;
  4430.         self.th_melee ();
  4431.     }
  4432. };
  4433.  
  4434. void (float dist, float turn) aibot_run_slide =
  4435. {
  4436.     local float ofs;
  4437.     local float rdir;
  4438.     local float rng;
  4439.     local float rnd;
  4440.     local float dis;
  4441.     local float trn;
  4442.     local float weap;
  4443.  
  4444.     trn = turn;
  4445.     self.ideal_yaw = vectoyaw ((self.enemy.origin - self.origin));
  4446.     ChangeYaw ();
  4447.     ofs = 90;
  4448.     dis = dist;
  4449.     self.strafeonly = (self.strafeonly - TRUE);
  4450.     if ((self.strafeonly > FALSE))
  4451.     {
  4452.         trn = NOTURN;
  4453.     }
  4454.     rdir = (random () * MOVETYPE_WALK);
  4455.     rng = botrange (self.enemy);
  4456.     if ((rng == RANGE_NEAR))
  4457.     {
  4458.         rdir = (rdir + 0.8);
  4459.     }
  4460.     else
  4461.     {
  4462.         if ((rng == RANGE_MELEE))
  4463.         {
  4464.             rdir = (rdir + 1.2);
  4465.             rnd = random ();
  4466.             weap = W_BestHeldWeapon ();
  4467.             if ((weap == IT_ROCKET_LAUNCHER))
  4468.             {
  4469.                 rnd = FALSE;
  4470.             }
  4471.             else
  4472.             {
  4473.                 if ((weap == IT_GRENADE_LAUNCHER))
  4474.                 {
  4475.                     rnd = FALSE;
  4476.                 }
  4477.                 else
  4478.                 {
  4479.                     if ((self.enemyrun > MOVETYPE_STEP))
  4480.                     {
  4481.                         rnd = TRUE;
  4482.                     }
  4483.                     else
  4484.                     {
  4485.                         if ((weap == IT_AXE))
  4486.                         {
  4487.                             rnd = TRUE;
  4488.                         }
  4489.                         else
  4490.                         {
  4491.                             if ((self.enemy.weapon == IT_ROCKET_LAUNCHER))
  4492.                             {
  4493.                                 rnd = TRUE;
  4494.                             }
  4495.                         }
  4496.                     }
  4497.                 }
  4498.             }
  4499.             if ((rnd < 0.3))
  4500.             {
  4501.                 if (botwalkmove ((self.ideal_yaw + 180), dis))
  4502.                 {
  4503.                     return;
  4504.                 }
  4505.             }
  4506.         }
  4507.         else
  4508.         {
  4509.             if ((rng == RANGE_MID))
  4510.             {
  4511.                 weap = W_BestHeldWeapon ();
  4512.                 if ((weap == IT_LIGHTNING))
  4513.                 {
  4514.                     rdir = (rdir - MOVETYPE_WALK);
  4515.                 }
  4516.                 else
  4517.                 {
  4518.                     rdir = (rdir - TRUE);
  4519.                 }
  4520.             }
  4521.             else
  4522.             {
  4523.                 if ((rng == RANGE_FAR))
  4524.                 {
  4525.                     rdir = (rdir - 2.5);
  4526.                 }
  4527.             }
  4528.         }
  4529.     }
  4530.     if ((self.weapon == IT_AXE))
  4531.     {
  4532.         rdir = FALSE;
  4533.     }
  4534.     else
  4535.     {
  4536.         if ((self.weapon == IT_ROCKET_LAUNCHER))
  4537.         {
  4538.             rdir = (rdir + 1.5);
  4539.         }
  4540.         else
  4541.         {
  4542.             if ((self.weapon == IT_GRENADE_LAUNCHER))
  4543.             {
  4544.                 rdir = (rdir + 1.5);
  4545.             }
  4546.         }
  4547.     }
  4548.     if ((self.enemy.weapon == IT_ROCKET_LAUNCHER))
  4549.     {
  4550.         rdir = (rdir + 1.5);
  4551.     }
  4552.     else
  4553.     {
  4554.         if ((self.enemy.weapon == IT_LIGHTNING))
  4555.         {
  4556.             rdir = (rdir + 1.5);
  4557.         }
  4558.     }
  4559.     if ((self.enemyrun > FL_CLIENT))
  4560.     {
  4561.         rdir = (rdir - FL_SWIM);
  4562.     }
  4563.     else
  4564.     {
  4565.         if ((self.origin_z > (self.enemy.origin_z + 130)))
  4566.         {
  4567.             rdir = ((rdir + 1.1) + random ());
  4568.             if ((rdir >= 1.5))
  4569.             {
  4570.                 trn = NOTURN;
  4571.             }
  4572.             if ((self.weapon == IT_AXE))
  4573.             {
  4574.                 trn = turn;
  4575.                 rdir = FALSE;
  4576.             }
  4577.         }
  4578.     }
  4579.     if ((rdir < 1.5))
  4580.     {
  4581.         if ((trn == CANTURN))
  4582.         {
  4583.             Botmovetogoal (dis);
  4584.             return;
  4585.         }
  4586.         if (botwalkmove (self.ideal_yaw, dis))
  4587.         {
  4588.             return;
  4589.         }
  4590.         ofs = 90;
  4591.     }
  4592.     else
  4593.     {
  4594.         if ((rdir < 2.4))
  4595.         {
  4596.             ofs = 45;
  4597.         }
  4598.     }
  4599.     if ((self.skil == FALSE))
  4600.     {
  4601.         return;
  4602.     }
  4603.     self.strafetime = (self.strafetime + 0.1);
  4604.     if ((self.skil < FL_SWIM))
  4605.     {
  4606.         if ((self.skil < TRUE))
  4607.         {
  4608.             dis = (0.7 * dis);
  4609.         }
  4610.         if ((self.strafetime == 0.1))
  4611.         {
  4612.             rnd = (random () * MOVETYPE_STEP);
  4613.             if ((self.skil >= TRUE))
  4614.             {
  4615.                 rnd = ((rnd - self.skil) + 0.5);
  4616.             }
  4617.             if ((rnd > self.skil))
  4618.             {
  4619.                 self.strafetime = FALSE;
  4620.                 return;
  4621.             }
  4622.         }
  4623.     }
  4624.     if ((self.strafetime > 0.4))
  4625.     {
  4626.         rnd = (random () * FL_SWIM);
  4627.         if ((rnd > 1.87))
  4628.         {
  4629.             if ((self.lefty & STRAFE_DIR))
  4630.             {
  4631.                 self.lefty = (self.lefty - STRAFE_DIR);
  4632.             }
  4633.             else
  4634.             {
  4635.                 self.lefty = (self.lefty + STRAFE_DIR);
  4636.             }
  4637.             self.strafetime = FALSE;
  4638.             return;
  4639.         }
  4640.     }
  4641.     if ((self.lefty & STRAFE_DIR))
  4642.     {
  4643.         ofs = (CONTENT_EMPTY * ofs);
  4644.     }
  4645.     if (botwalkmove ((self.ideal_yaw + ofs), dis))
  4646.     {
  4647.         return;
  4648.     }
  4649.     self.strafetime = FALSE;
  4650.     if ((self.lefty & STRAFE_DIR))
  4651.     {
  4652.         self.lefty = (self.lefty - STRAFE_DIR);
  4653.     }
  4654.     else
  4655.     {
  4656.         self.lefty = (self.lefty + STRAFE_DIR);
  4657.     }
  4658.     if (((ofs == 90) || (ofs == -90)))
  4659.     {
  4660.         rnd = random ();
  4661.         if ((rnd < 0.05))
  4662.         {
  4663.             if ((trn == CANTURN))
  4664.             {
  4665.                 Botmovetogoal (dis);
  4666.                 return;
  4667.             }
  4668.         }
  4669.         if ((rnd < 0.5))
  4670.         {
  4671.             walkmove ((self.ideal_yaw + 180), (dis * 0.5));
  4672.         }
  4673.         return;
  4674.     }
  4675.     botwalkmove (self.ideal_yaw, dis);
  4676. };
  4677. void (float dist) ai_botgetGoody;
  4678.  
  4679. void (float dist) ai_botcharge =
  4680. {
  4681.     local float rng;
  4682.     local float oldrng;
  4683.  
  4684.     if ((self.lefty & GETGOODY))
  4685.     {
  4686.         ai_botgetGoody (dist);
  4687.         return;
  4688.     }
  4689.     if (enemyvisible (self.enemy))
  4690.     {
  4691.         rng = vlen ((self.enemy.origin - self.origin));
  4692.         oldrng = vlen ((self.goalentity.origin - self.origin));
  4693.         if ((self.goalentity.classname != "BotTarget"))
  4694.         {
  4695.             objerror ("bad bot target in bot_ai! 3\n");
  4696.         }
  4697.         setorigin (self.goalentity, self.enemy.origin);
  4698.         if ((self.enemyrun > FALSE))
  4699.         {
  4700.             self.enemyrun = (self.enemyrun - TRUE);
  4701.         }
  4702.         if ((rng > (oldrng + MOVETYPE_BOUNCE)))
  4703.         {
  4704.             self.enemyrun = (self.enemyrun + FL_SWIM);
  4705.         }
  4706.     }
  4707.     aibot_run_slide (dist, NOTURN);
  4708. };
  4709.  
  4710. void (float dist) ai_botnailcharge =
  4711. {
  4712.     local float rnd;
  4713.  
  4714.     if (!enemyvisible (self.enemy))
  4715.     {
  4716.         self.think = self.th_run;
  4717.     }
  4718.     if (!FacingIdeal ())
  4719.     {
  4720.         self.think = self.th_run;
  4721.     }
  4722.     if ((self.enemy.deadflag != DEAD_NO))
  4723.     {
  4724.         endEnemy ();
  4725.         return;
  4726.     }
  4727.     ai_botcharge (dist);
  4728. };
  4729. float (float minweight) aibot_checkforGoodies;
  4730.  
  4731. void (float dist) ai_botrun =
  4732. {
  4733.     local vector delta;
  4734.     local float axis;
  4735.     local float rng;
  4736.     local float oldrng;
  4737.     local float direct;
  4738.     local float ang_rint;
  4739.     local float ang_floor;
  4740.     local float ang_ceil;
  4741.  
  4742.     if ((self.enemy.deadflag != DEAD_NO))
  4743.     {
  4744.         endEnemy ();
  4745.         return;
  4746.     }
  4747.     if (!self.enemy)
  4748.     {
  4749.         endEnemy ();
  4750.         return;
  4751.     }
  4752.     if ((self.lefty & GETGOODY))
  4753.     {
  4754.         ai_botgetGoody (dist);
  4755.         return;
  4756.     }
  4757.     enemy_vis = enemyvisible (self.enemy);
  4758.     if ((enemy_vis || Spotvisible (self.enemy)))
  4759.     {
  4760.         rng = vlen ((self.enemy.origin - self.origin));
  4761.         oldrng = vlen ((self.goalentity.origin - self.origin));
  4762.         if ((self.enemyrun > FALSE))
  4763.         {
  4764.             self.enemyrun = (self.enemyrun - TRUE);
  4765.         }
  4766.         if ((rng > (oldrng + MOVETYPE_BOUNCE)))
  4767.         {
  4768.             self.enemyrun = (self.enemyrun + FL_SWIM);
  4769.         }
  4770.         if ((self.goalentity.classname != "BotTarget"))
  4771.         {
  4772.             objerror ("bad bot target in bot_ai! 4\n");
  4773.         }
  4774.         setorigin (self.goalentity, self.enemy.origin);
  4775.         self.search_time = (time + MOVETYPE_PUSH);
  4776.     }
  4777.     if ((self.search_time < time))
  4778.     {
  4779.         endEnemy ();
  4780.         BotFindTarget ();
  4781.         return;
  4782.     }
  4783.     if (((self.lefty & LOCAL_TIME) > MOVETYPE_FLY))
  4784.     {
  4785.         self.lefty = (self.lefty - (self.lefty & LOCAL_TIME));
  4786.         self.lastseenpos = self.goalentity.origin;
  4787.         if (aibot_checkforGoodies (DONT_WANT))
  4788.         {
  4789.             ai_botgetGoody (dist);
  4790.             return;
  4791.         }
  4792.     }
  4793.     self.lefty = (self.lefty + TRUE);
  4794.     if (RunAway ())
  4795.     {
  4796.         self.lefty = (self.lefty - (self.lefty & LOCAL_TIME));
  4797.         self.lastseenpos = self.goalentity.origin;
  4798.         if (aibot_checkforGoodies (DONT_WANT))
  4799.         {
  4800.             ai_botgetGoody (dist);
  4801.             return;
  4802.         }
  4803.     }
  4804.     enemy_infront = infrontofbot (self.enemy);
  4805.     enemy_yaw = vectoyaw ((self.enemy.origin - self.origin));
  4806.     if (!enemy_vis)
  4807.     {
  4808.         aibot_setupchase ();
  4809.         Botmovetogoal (dist);
  4810.         return;
  4811.     }
  4812.     if ((self.attack_state == AS_MELEE))
  4813.     {
  4814.         aibot_run_melee ();
  4815.     }
  4816.     CheckBotAttack ();
  4817.     aibot_run_slide (dist, CANTURN);
  4818.     return;
  4819. };
  4820.  
  4821. void () aibot_setupchase =
  4822. {
  4823.     local entity pth;
  4824.  
  4825.     self.think = bot_chase;
  4826.     if (TrueReachable (self.goalentity))
  4827.     {
  4828.         return;
  4829.     }
  4830.     if (RunAway ())
  4831.     {
  4832.         self.lefty = (self.lefty - (self.lefty & LOCAL_TIME));
  4833.         aibot_checkforGoodies ((WANT - TRUE));
  4834.         self.lastseenpos = self.goalentity.origin;
  4835.         return;
  4836.     }
  4837.     pth = BestChaseRoute (self, self.enemy);
  4838.     if ((self.goalentity.classname != "BotTarget"))
  4839.     {
  4840.         objerror ("bad bot target in bot_ai! 1\n");
  4841.     }
  4842.     if ((pth != self.enemy))
  4843.     {
  4844.         setorigin (self.goalentity, pth.origin);
  4845.     }
  4846.     self.search_time = (time + MOVETYPE_TOSS);
  4847. };
  4848.  
  4849. void (float dist) aibot_chase =
  4850. {
  4851.     local entity olden;
  4852.     local float weap;
  4853.     local float rnd;
  4854.  
  4855.     if ((self.enemy.deadflag != DEAD_NO))
  4856.     {
  4857.         endEnemy ();
  4858.         return;
  4859.     }
  4860.     if ((self.lefty & GETGOODY))
  4861.     {
  4862.         ai_botgetGoody (dist);
  4863.         return;
  4864.     }
  4865.     enemy_vis = enemyvisible (self.enemy);
  4866.     rnd = random ();
  4867.     if ((rnd < 0.9))
  4868.     {
  4869.         enemy_vis = enemy_vis;
  4870.     }
  4871.     if (enemy_vis)
  4872.     {
  4873.         if ((self.goalentity.classname != "BotTarget"))
  4874.         {
  4875.             objerror ("bad bot target in bot_ai! 1\n");
  4876.         }
  4877.         setorigin (self.goalentity, self.enemy.origin);
  4878.         self.search_time = (time + MOVETYPE_FLY);
  4879.         self.think = self.th_run;
  4880.         Botmovetogoal (dist);
  4881.         return;
  4882.     }
  4883.     if (RunAway ())
  4884.     {
  4885.         if ((self.search_time < time))
  4886.         {
  4887.             endEnemy ();
  4888.             return;
  4889.         }
  4890.         self.lefty = (self.lefty - (self.lefty & LOCAL_TIME));
  4891.         if (aibot_checkforGoodies ((WANT - TRUE)))
  4892.         {
  4893.             ai_botgetGoody (dist);
  4894.             self.lastseenpos = self.goalentity.origin;
  4895.             return;
  4896.         }
  4897.     }
  4898.     if ((self.enemy.items & IT_INVISIBILITY))
  4899.     {
  4900.         if ((self.skil < MOVETYPE_WALK))
  4901.         {
  4902.             endEnemy ();
  4903.             return;
  4904.         }
  4905.     }
  4906.     if (((self.lefty & LOCAL_TIME) > MOVETYPE_FLY))
  4907.     {
  4908.         self.lastseenpos = self.goalentity.origin;
  4909.         self.lefty = (self.lefty - (self.lefty & LOCAL_TIME));
  4910.         if (aibot_checkforGoodies ((MUST_HAVE - MOVETYPE_WALK)))
  4911.         {
  4912.             ai_botgetGoody (dist);
  4913.             return;
  4914.         }
  4915.     }
  4916.     self.lefty = (self.lefty + TRUE);
  4917.     olden = self.enemy;
  4918.     if (BotFindTarget ())
  4919.     {
  4920.         if ((olden.enemy == self))
  4921.         {
  4922.             olden.enemy = world;
  4923.         }
  4924.         return;
  4925.     }
  4926.     if ((self.search_time < time))
  4927.     {
  4928.         endEnemy ();
  4929.         return;
  4930.     }
  4931.     if (CheckReboundAttack ())
  4932.     {
  4933.         return;
  4934.     }
  4935.     Botmovetogoal (dist);
  4936. };
  4937.  
  4938. float (float minweight) aibot_checkforGoodies =
  4939. {
  4940.     local entity e;
  4941.     local entity botTarget;
  4942.     local float AFRAID;
  4943.     local float steps;
  4944.     local float best;
  4945.     local float weight;
  4946.     local float goody_yaw;
  4947.     local float lnd;
  4948.     local float weap;
  4949.     local float minimum;
  4950.     local vector spot;
  4951.  
  4952.     if ((self.air_finished < (time + MOVETYPE_FLYMISSILE)))
  4953.     {
  4954.         goForAir ();
  4955.         self.lefty = (self.lefty | GETGOODY);
  4956.         self.goody_time = (time + MOVETYPE_WALK);
  4957.         return (TRUE);
  4958.     }
  4959.     AFRAID = RunAway ();
  4960.     botTarget = self.goalentity;
  4961.     e = findradius (self.origin, SEARCH_RADIUS);
  4962.     best = DONT_WANT;
  4963.     while (e)
  4964.     {
  4965.         weight = DONT_WANT;
  4966.         if ((e.origin_z > (self.origin_z + (0.7 * MAXJUMP))))
  4967.         {
  4968.             weight = DONT_WANT;
  4969.         }
  4970.         else
  4971.         {
  4972.             if (((e.pathtype == DROPPED) || (e.pathtype == TELEPORT)))
  4973.             {
  4974.                 weight = DONT_WANT;
  4975.                 if (AFRAID)
  4976.                 {
  4977.                     weight = RunAwayWeight (e);
  4978.                 }
  4979.             }
  4980.             else
  4981.             {
  4982.                 if ((e.pathtype != REGULARTARGET))
  4983.                 {
  4984.                     weight = DONT_WANT;
  4985.                 }
  4986.                 else
  4987.                 {
  4988.                     if ((e.solid != SOLID_TRIGGER))
  4989.                     {
  4990.                         weight = DONT_WANT;
  4991.                     }
  4992.                     else
  4993.                     {
  4994.                         if (!e.istrigger)
  4995.                         {
  4996.                             weight = itemweight (e);
  4997.                             if ((weight < MUST_HAVE))
  4998.                             {
  4999.                                 if ((((e.origin_z < self.enemy.absmin_z) && (e.origin_z < self.absmin_z)) && !AFRAID))
  5000.                                 {
  5001.                                     weight = DONT_WANT;
  5002.                                 }
  5003.                             }
  5004.                         }
  5005.                     }
  5006.                 }
  5007.             }
  5008.         }
  5009.         if ((weight > best))
  5010.         {
  5011.             botTarget.goalentity = e;
  5012.             best = weight;
  5013.         }
  5014.         e = e.chain;
  5015.     }
  5016.     minimum = minweight;
  5017.     if ((self.skil < TRUE))
  5018.     {
  5019.         if ((minimum < (WANT + FL_SWIM)))
  5020.         {
  5021.             minimum = (WANT + FL_SWIM);
  5022.         }
  5023.     }
  5024.     if ((best > DONT_WANT))
  5025.     {
  5026.         if (((best > minimum) || AFRAID))
  5027.         {
  5028.             if ((botTarget.classname != "BotTarget"))
  5029.             {
  5030.                 objerror ("bad bot target in bot_ai! 6\n");
  5031.             }
  5032.             setorigin (botTarget, botTarget.goalentity.origin);
  5033.             self.lefty = (self.lefty | GETGOODY);
  5034.             self.goody_time = (time + MOVETYPE_WALK);
  5035.             return (TRUE);
  5036.         }
  5037.     }
  5038.     botTarget.goalentity = self.enemy;
  5039.     return (FALSE);
  5040. };
  5041.  
  5042. void (float dist) ai_endgetGoody =
  5043. {
  5044.     if ((self.lefty & GETGOODY))
  5045.     {
  5046.         self.lefty = (self.lefty - GETGOODY);
  5047.     }
  5048.     if ((self.goalentity.classname != "BotTarget"))
  5049.     {
  5050.         objerror ("bad bot target in bot_ai! 7\n");
  5051.     }
  5052.     setorigin (self.goalentity, self.lastseenpos);
  5053.     self.goalentity.goalentity = self.enemy;
  5054.     if (enemyvisible (self.enemy))
  5055.     {
  5056.         self.lastseenpos = self.enemy.origin;
  5057.         if ((self.attack_finished < time))
  5058.         {
  5059.             if ((self.attack_state == AS_MELEE))
  5060.             {
  5061.                 aibot_run_melee ();
  5062.             }
  5063.             CheckBotAttack ();
  5064.         }
  5065.     }
  5066.     Botmovetogoal (dist);
  5067. };
  5068.  
  5069. void (float dist) ai_botgetGoody =
  5070. {
  5071.     local float goody_yaw;
  5072.     local float dis;
  5073.     local float weap;
  5074.  
  5075.     self.search_time = (self.search_time + 0.1);
  5076.     if ((time > self.goody_time))
  5077.     {
  5078.         ai_endgetGoody (dist);
  5079.         return;
  5080.     }
  5081.     if ((self.goalentity.goalentity.solid == SOLID_NOT))
  5082.     {
  5083.         ai_endgetGoody (dist);
  5084.         return;
  5085.     }
  5086.     if (!Spotvisible (self.goalentity.goalentity))
  5087.     {
  5088.         if ((self.air_finished > MOVETYPE_FLYMISSILE))
  5089.         {
  5090.             ai_endgetGoody (dist);
  5091.             return;
  5092.         }
  5093.     }
  5094.     goody_yaw = vectoyaw ((self.goalentity.origin - self.origin));
  5095.     if (enemyvisible (self.enemy))
  5096.     {
  5097.         self.lastseenpos = self.enemy.origin;
  5098.         weap = W_BestBotWeapon ();
  5099.         if ((((self.enemy.items & IT_INVULNERABILITY) || (self.skil < TRUE)) || (weap == IT_AXE)))
  5100.         {
  5101.             self.ideal_yaw = goody_yaw;
  5102.             ChangeYaw ();
  5103.         }
  5104.         else
  5105.         {
  5106.             if ((self.attack_finished < time))
  5107.             {
  5108.                 self.ideal_yaw = vectoyaw ((self.enemy.origin - self.origin));
  5109.                 ChangeYaw ();
  5110.                 if ((self.attack_state == AS_MELEE))
  5111.                 {
  5112.                     aibot_run_melee ();
  5113.                 }
  5114.                 CheckBotAttack ();
  5115.             }
  5116.         }
  5117.     }
  5118.     if ((self.air_finished < MOVETYPE_TOSS))
  5119.     {
  5120.         waterupz (SVC_TEMPENTITY);
  5121.         return;
  5122.     }
  5123.     if ((self.flags & FL_SWIM))
  5124.     {
  5125.         if (waterupdown (dist))
  5126.         {
  5127.             return;
  5128.         }
  5129.     }
  5130.     dis = vlen ((self.origin - self.goalentity.origin));
  5131.     if ((dis > dist))
  5132.     {
  5133.         dis = dist;
  5134.     }
  5135.     else
  5136.     {
  5137.         if ((self.goalentity.goalentity.pathtype == DROPPED))
  5138.         {
  5139.             ai_endgetGoody (dist);
  5140.             return;
  5141.         }
  5142.     }
  5143.     if (botwalkmove (goody_yaw, dis))
  5144.     {
  5145.         return;
  5146.     }
  5147.     if (Bot_tryjump (270, dist, FALSE))
  5148.     {
  5149.         return;
  5150.     }
  5151.     if ((self.lefty & GETGOODY))
  5152.     {
  5153.         self.lefty = (self.lefty - GETGOODY);
  5154.     }
  5155.     if ((self.goalentity.classname != "BotTarget"))
  5156.     {
  5157.         objerror ("bad bot target in bot_ai! 8\n");
  5158.     }
  5159.     setorigin (self.goalentity, self.lastseenpos);
  5160.     self.goalentity.goalentity = self.enemy;
  5161. };
  5162.  
  5163.  
  5164. void () bot_start = [ 12, bot_walk ]
  5165. {
  5166.     local string tmp;
  5167.  
  5168.     BotPostThink ();
  5169.     droptofloor ();
  5170.     self.nextthink = ((time + 0.2) + (0.2 * random ()));
  5171.     if ((self.skil < MOVETYPE_WALK))
  5172.     {
  5173.         self.nextthink = (self.nextthink + (0.1 * (MOVETYPE_WALK - self.skil)));
  5174.     }
  5175. };
  5176.  
  5177. void () bot_stand1 = [ 12, bot_walk ]
  5178. {
  5179.     ai_botstand ();
  5180.     BotPostThink ();
  5181. };
  5182.  
  5183. void () bot_walk = [ 6, bot_walk ]
  5184. {
  5185.     self.weaponframe = FALSE;
  5186.     if ((self.weapon == IT_AXE))
  5187.     {
  5188.         if ((self.walkframe == MOVETYPE_TOSS))
  5189.         {
  5190.             self.walkframe = FALSE;
  5191.         }
  5192.         self.frame = (FALSE + self.walkframe);
  5193.     }
  5194.     else
  5195.     {
  5196.         if ((self.walkframe == MOVETYPE_TOSS))
  5197.         {
  5198.             self.walkframe = FALSE;
  5199.         }
  5200.         self.frame = (self.frame + self.walkframe);
  5201.     }
  5202.     self.walkframe = (self.walkframe + TRUE);
  5203.     ai_botseek (BOTSPEED);
  5204.     BotPostThink ();
  5205. };
  5206.  
  5207. void () bot_run = [ 6, bot_run ]
  5208. {
  5209.     self.weaponframe = FALSE;
  5210.     if ((self.weapon == IT_AXE))
  5211.     {
  5212.         if ((self.walkframe == MOVETYPE_TOSS))
  5213.         {
  5214.             self.walkframe = FALSE;
  5215.         }
  5216.         self.frame = (FALSE + self.walkframe);
  5217.     }
  5218.     else
  5219.     {
  5220.         if ((self.walkframe == MOVETYPE_TOSS))
  5221.         {
  5222.             self.walkframe = FALSE;
  5223.         }
  5224.         self.frame = (self.frame + self.walkframe);
  5225.     }
  5226.     self.walkframe = (self.walkframe + TRUE);
  5227.     ai_botrun (BOTSPEED);
  5228.     BotPostThink ();
  5229. };
  5230.  
  5231. void () bot_chase = [ 6, bot_chase ]
  5232. {
  5233.     self.weaponframe = FALSE;
  5234.     if ((self.weapon == IT_AXE))
  5235.     {
  5236.         if ((self.walkframe == MOVETYPE_TOSS))
  5237.         {
  5238.             self.walkframe = FALSE;
  5239.         }
  5240.         self.frame = (FALSE + self.walkframe);
  5241.     }
  5242.     else
  5243.     {
  5244.         if ((self.walkframe == MOVETYPE_TOSS))
  5245.         {
  5246.             self.walkframe = FALSE;
  5247.         }
  5248.         self.frame = (self.frame + self.walkframe);
  5249.     }
  5250.     self.walkframe = (self.walkframe + TRUE);
  5251.     aibot_chase (BOTSPEED);
  5252.     BotPostThink ();
  5253. };
  5254.  
  5255. void () bot_shot1 = [ 113, bot_shot2 ]
  5256. {
  5257.     self.weaponframe = TRUE;
  5258.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5259. };
  5260.  
  5261. void () bot_shot2 = [ 114, bot_shot3 ]
  5262. {
  5263.     self.weaponframe = FL_SWIM;
  5264.     if ((self.skil > 0.9))
  5265.     {
  5266.         ai_botcharge (BOTSPEED);
  5267.     }
  5268.     BotPostThink ();
  5269. };
  5270.  
  5271. void () bot_shot3 = [ 115, bot_shot4 ]
  5272. {
  5273.     self.weaponframe = MOVETYPE_WALK;
  5274.     if ((self.skil > FALSE))
  5275.     {
  5276.         ai_botcharge (BOTSPEED);
  5277.     }
  5278.     BotPostThink ();
  5279. };
  5280.  
  5281. void () bot_shot4 = [ 116, bot_shot5 ]
  5282. {
  5283.     self.weaponframe = MOVETYPE_STEP;
  5284.     if ((self.skil > FALSE))
  5285.     {
  5286.         ai_botcharge (BOTSPEED);
  5287.     }
  5288.     else
  5289.     {
  5290.         ai_botcharge ((BOTSPEED * 0.5));
  5291.     }
  5292.     BotPostThink ();
  5293. };
  5294.  
  5295. void () bot_shot5 = [ 117, bot_shot6 ]
  5296. {
  5297.     self.weaponframe = MOVETYPE_FLY;
  5298.     ai_botcharge (BOTSPEED);
  5299.     BotPostThink ();
  5300. };
  5301.  
  5302. void () bot_shot6 = [ 118, bot_run ]
  5303. {
  5304.     self.weaponframe = MOVETYPE_TOSS;
  5305.     ai_botcharge (BOTSPEED);
  5306.     BotPostThink ();
  5307. };
  5308.  
  5309. void () bot_trigger1 = [ 113, bot_trigger2 ]
  5310. {
  5311.     self.weaponframe = TRUE;
  5312.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5313. };
  5314.  
  5315. void () bot_trigger2 = [ 114, bot_trigger3 ]
  5316. {
  5317.     self.weaponframe = FL_SWIM;
  5318.     ai_botseek (BOTSPEED);
  5319.     BotPostThink ();
  5320. };
  5321.  
  5322. void () bot_trigger3 = [ 115, bot_trigger4 ]
  5323. {
  5324.     self.weaponframe = MOVETYPE_WALK;
  5325.     ai_botseek (BOTSPEED);
  5326.     BotPostThink ();
  5327. };
  5328.  
  5329. void () bot_trigger4 = [ 116, bot_trigger5 ]
  5330. {
  5331.     self.weaponframe = MOVETYPE_STEP;
  5332.     ai_botseek (BOTSPEED);
  5333.     BotPostThink ();
  5334. };
  5335.  
  5336. void () bot_trigger5 = [ 117, bot_trigger6 ]
  5337. {
  5338.     self.weaponframe = MOVETYPE_FLY;
  5339.     ai_botseek (BOTSPEED);
  5340.     BotPostThink ();
  5341. };
  5342.  
  5343. void () bot_trigger6 = [ 118, bot_walk ]
  5344. {
  5345.     self.weaponframe = MOVETYPE_TOSS;
  5346.     ai_botseek (BOTSPEED);
  5347.     BotPostThink ();
  5348. };
  5349.  
  5350. void () bot_axe1 = [ 119, bot_axe2 ]
  5351. {
  5352.     self.weaponframe = TRUE;
  5353. };
  5354.  
  5355. void () bot_axe2 = [ 120, bot_axe3 ]
  5356. {
  5357.     self.weaponframe = FL_SWIM;
  5358.     ai_botcharge (BOTSPEED);
  5359.     BotPostThink ();
  5360. };
  5361.  
  5362. void () bot_axe3 = [ 121, bot_axe4 ]
  5363. {
  5364.     self.weaponframe = MOVETYPE_WALK;
  5365.     W_FireAxe ();
  5366.     BotPostThink ();
  5367. };
  5368.  
  5369. void () bot_axe4 = [ 122, bot_run ]
  5370. {
  5371.     self.weaponframe = MOVETYPE_STEP;
  5372.     ai_botcharge (BOTSPEED);
  5373.     BotPostThink ();
  5374. };
  5375.  
  5376. void () bot_axeb1 = [ 125, bot_axeb2 ]
  5377. {
  5378.     self.weaponframe = MOVETYPE_FLY;
  5379. };
  5380.  
  5381. void () bot_axeb2 = [ 126, bot_axeb3 ]
  5382. {
  5383.     self.weaponframe = MOVETYPE_TOSS;
  5384.     ai_botcharge (BOTSPEED);
  5385.     BotPostThink ();
  5386. };
  5387.  
  5388. void () bot_axeb3 = [ 127, bot_axeb4 ]
  5389. {
  5390.     self.weaponframe = MOVETYPE_PUSH;
  5391.     W_FireAxe ();
  5392.     ai_botcharge (BOTSPEED);
  5393.     BotPostThink ();
  5394. };
  5395.  
  5396. void () bot_axeb4 = [ 128, bot_run ]
  5397. {
  5398.     self.weaponframe = FL_CLIENT;
  5399.     ai_botcharge (BOTSPEED);
  5400.     BotPostThink ();
  5401. };
  5402.  
  5403. void () bot_axec1 = [ 131, bot_axec2 ]
  5404. {
  5405.     self.weaponframe = TRUE;
  5406. };
  5407.  
  5408. void () bot_axec2 = [ 132, bot_axec3 ]
  5409. {
  5410.     self.weaponframe = FL_SWIM;
  5411.     ai_botcharge (BOTSPEED);
  5412.     BotPostThink ();
  5413. };
  5414.  
  5415. void () bot_axec3 = [ 133, bot_axec4 ]
  5416. {
  5417.     self.weaponframe = MOVETYPE_WALK;
  5418.     W_FireAxe ();
  5419.     ai_botcharge (BOTSPEED);
  5420.     BotPostThink ();
  5421. };
  5422.  
  5423. void () bot_axec4 = [ 134, bot_run ]
  5424. {
  5425.     self.weaponframe = MOVETYPE_STEP;
  5426.     ai_botcharge (BOTSPEED);
  5427.     BotPostThink ();
  5428. };
  5429.  
  5430. void () bot_axed1 = [ 137, bot_axed2 ]
  5431. {
  5432.     self.weaponframe = MOVETYPE_FLY;
  5433. };
  5434.  
  5435. void () bot_axed2 = [ 138, bot_axed3 ]
  5436. {
  5437.     self.weaponframe = MOVETYPE_TOSS;
  5438.     ai_botcharge (BOTSPEED);
  5439.     BotPostThink ();
  5440. };
  5441.  
  5442. void () bot_axed3 = [ 139, bot_axed4 ]
  5443. {
  5444.     self.weaponframe = MOVETYPE_PUSH;
  5445.     W_FireAxe ();
  5446.     ai_botcharge (BOTSPEED);
  5447.     BotPostThink ();
  5448. };
  5449.  
  5450. void () bot_axed4 = [ 140, bot_run ]
  5451. {
  5452.     self.weaponframe = FL_CLIENT;
  5453.     ai_botcharge (BOTSPEED);
  5454.     BotPostThink ();
  5455. };
  5456.  
  5457. void () dmbot_melee =
  5458. {
  5459.     self.weapon = W_BestBotWeapon ();
  5460.     W_BotAttack ();
  5461. };
  5462.  
  5463. void () bot_nail1 = [ 103, bot_nail2 ]
  5464. {
  5465.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5466.     self.weaponframe = (self.weaponframe + TRUE);
  5467.     if ((self.weaponframe == MOVETYPE_FLYMISSILE))
  5468.     {
  5469.         self.weaponframe = TRUE;
  5470.     }
  5471.     SuperDamageSound ();
  5472.     W_FireSpikes (MOVETYPE_STEP);
  5473.     ai_botnailcharge (BOTSPEED);
  5474.     self.attack_finished = (time + 0.2);
  5475.     BotPostThink ();
  5476. };
  5477.  
  5478. void () bot_nail2 = [ 104, bot_nail1 ]
  5479. {
  5480.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5481.     self.weaponframe = (self.weaponframe + TRUE);
  5482.     if ((self.weaponframe == MOVETYPE_FLYMISSILE))
  5483.     {
  5484.         self.weaponframe = TRUE;
  5485.     }
  5486.     SuperDamageSound ();
  5487.     W_FireSpikes (CONTENT_SLIME);
  5488.     ai_botnailcharge (BOTSPEED);
  5489.     self.attack_finished = (time + 0.2);
  5490.     BotPostThink ();
  5491. };
  5492.  
  5493. void () bot_light1 = [ 105, bot_light2 ]
  5494. {
  5495.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5496.     self.weaponframe = (self.weaponframe + TRUE);
  5497.     if ((self.weaponframe == MOVETYPE_FLY))
  5498.     {
  5499.         self.weaponframe = TRUE;
  5500.     }
  5501.     SuperDamageSound ();
  5502.     W_FireLightning ();
  5503.     ai_botnailcharge (BOTSPEED);
  5504.     self.attack_finished = (time + 0.2);
  5505.     BotPostThink ();
  5506. };
  5507.  
  5508. void () bot_light2 = [ 106, bot_light1 ]
  5509. {
  5510.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5511.     self.weaponframe = (self.weaponframe + TRUE);
  5512.     if ((self.weaponframe == MOVETYPE_FLY))
  5513.     {
  5514.         self.weaponframe = TRUE;
  5515.     }
  5516.     SuperDamageSound ();
  5517.     W_FireLightning ();
  5518.     ai_botnailcharge (BOTSPEED);
  5519.     self.attack_finished = (time + 0.2);
  5520.     BotPostThink ();
  5521. };
  5522.  
  5523. void () bot_rocket1 = [ 107, bot_rocket2 ]
  5524. {
  5525.     self.weaponframe = TRUE;
  5526.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5527.     BotPostThink ();
  5528. };
  5529.  
  5530. void () bot_rocket2 = [ 108, bot_rocket3 ]
  5531. {
  5532.     self.weaponframe = FL_SWIM;
  5533.     if ((self.skil > FL_SWIM))
  5534.     {
  5535.         ai_botcharge (BOTSPEED);
  5536.     }
  5537.     BotPostThink ();
  5538. };
  5539.  
  5540. void () bot_rocket3 = [ 109, bot_rocket4 ]
  5541. {
  5542.     self.weaponframe = MOVETYPE_WALK;
  5543.     if ((self.skil > TRUE))
  5544.     {
  5545.         ai_botcharge (BOTSPEED);
  5546.     }
  5547.     BotPostThink ();
  5548. };
  5549.  
  5550. void () bot_rocket4 = [ 110, bot_rocket5 ]
  5551. {
  5552.     self.weaponframe = MOVETYPE_STEP;
  5553.     if ((self.skil > TRUE))
  5554.     {
  5555.         ai_botcharge (BOTSPEED);
  5556.     }
  5557.     BotPostThink ();
  5558. };
  5559.  
  5560. void () bot_rocket5 = [ 111, bot_rocket6 ]
  5561. {
  5562.     self.weaponframe = MOVETYPE_FLY;
  5563.     if ((self.skil > FALSE))
  5564.     {
  5565.         ai_botcharge (BOTSPEED);
  5566.     }
  5567.     BotPostThink ();
  5568. };
  5569.  
  5570. void () bot_rocket6 = [ 112, bot_run ]
  5571. {
  5572.     self.weaponframe = MOVETYPE_TOSS;
  5573.     ai_botcharge (BOTSPEED);
  5574.     BotPostThink ();
  5575. };
  5576.  
  5577. void () bot_rebound1 = [ 107, bot_rebound2 ]
  5578. {
  5579.     self.weaponframe = TRUE;
  5580.     self.effects = (self.effects | EF_MUZZLEFLASH);
  5581.     BotPostThink ();
  5582. };
  5583.  
  5584. void () bot_rebound2 = [ 108, bot_rebound3 ]
  5585. {
  5586.     self.weaponframe = FL_SWIM;
  5587.     BotPostThink ();
  5588. };
  5589.  
  5590. void () bot_rebound3 = [ 109, bot_rebound4 ]
  5591. {
  5592.     self.weaponframe = MOVETYPE_WALK;
  5593.     BotPostThink ();
  5594. };
  5595.  
  5596. void () bot_rebound4 = [ 110, bot_rebound5 ]
  5597. {
  5598.     self.weaponframe = MOVETYPE_STEP;
  5599.     aibot_chase (BOTSPEED);
  5600.     BotPostThink ();
  5601. };
  5602.  
  5603. void () bot_rebound5 = [ 111, bot_rebound6 ]
  5604. {
  5605.     self.weaponframe = MOVETYPE_FLY;
  5606.     aibot_chase (BOTSPEED);
  5607.     BotPostThink ();
  5608. };
  5609.  
  5610. void () bot_rebound6 = [ 112, bot_chase ]
  5611. {
  5612.     self.weaponframe = MOVETYPE_TOSS;
  5613.     aibot_chase (BOTSPEED);
  5614.     BotPostThink ();
  5615. };
  5616.  
  5617. void () bot_pain1 = [ 35, bot_pain2 ]
  5618. {
  5619.     PainSound ();
  5620.     self.weaponframe = FALSE;
  5621. };
  5622.  
  5623. void () bot_pain2 = [ 36, bot_pain3 ]
  5624. {
  5625.     local float r;
  5626.  
  5627.     r = ((MOVETYPE_STEP * random ()) + self.skil);
  5628.     if ((r > FL_SWIM))
  5629.     {
  5630.         ai_botrun (BOTSPEED);
  5631.     }
  5632.     else
  5633.     {
  5634.         ai_botcharge (BOTSPEED);
  5635.     }
  5636.     BotPostThink ();
  5637. };
  5638.  
  5639. void () bot_pain3 = [ 37, bot_pain4 ]
  5640. {
  5641.     if ((self.skil >= TRUE))
  5642.     {
  5643.         ai_botrun (BOTSPEED);
  5644.     }
  5645.     else
  5646.     {
  5647.         ai_botcharge (BOTSPEED);
  5648.     }
  5649.     BotPostThink ();
  5650. };
  5651.  
  5652. void () bot_pain4 = [ 38, bot_pain5 ]
  5653. {
  5654.     if ((self.skil > FALSE))
  5655.     {
  5656.         ai_botrun (BOTSPEED);
  5657.     }
  5658.     else
  5659.     {
  5660.         ai_botcharge (BOTSPEED);
  5661.     }
  5662.     BotPostThink ();
  5663. };
  5664.  
  5665. void () bot_pain5 = [ 39, bot_pain6 ]
  5666. {
  5667.     if ((self.skil > FL_SWIM))
  5668.     {
  5669.         ai_botrun (BOTSPEED);
  5670.     }
  5671.     else
  5672.     {
  5673.         ai_botcharge (BOTSPEED);
  5674.     }
  5675.     BotPostThink ();
  5676. };
  5677.  
  5678. void () bot_pain6 = [ 40, bot_run ]
  5679. {
  5680.     ai_botrun (BOTSPEED);
  5681.     BotPostThink ();
  5682. };
  5683.  
  5684. void () bot_axpain1 = [ 29, bot_axpain2 ]
  5685. {
  5686.     PainSound ();
  5687.     self.weaponframe = FALSE;
  5688.     BotPostThink ();
  5689. };
  5690.  
  5691. void () bot_axpain2 = [ 30, bot_axpain3 ]
  5692. {
  5693.     local float r;
  5694.  
  5695.     r = ((MOVETYPE_STEP * random ()) + self.skil);
  5696.     if ((r > FL_SWIM))
  5697.     {
  5698.         ai_botrun (BOTSPEED);
  5699.     }
  5700.     else
  5701.     {
  5702.         ai_botcharge (BOTSPEED);
  5703.     }
  5704.     BotPostThink ();
  5705. };
  5706.  
  5707. void () bot_axpain3 = [ 31, bot_axpain4 ]
  5708. {
  5709.     if ((self.skil >= TRUE))
  5710.     {
  5711.         ai_botrun (BOTSPEED);
  5712.     }
  5713.     BotPostThink ();
  5714. };
  5715.  
  5716. void () bot_axpain4 = [ 32, bot_axpain5 ]
  5717. {
  5718.     ai_botcharge (BOTSPEED);
  5719.     BotPostThink ();
  5720. };
  5721.  
  5722. void () bot_axpain5 = [ 33, bot_axpain6 ]
  5723. {
  5724.     ai_botrun (BOTSPEED);
  5725.     BotPostThink ();
  5726. };
  5727.  
  5728. void () bot_axpain6 = [ 34, bot_run ]
  5729. {
  5730.     ai_botrun (BOTSPEED);
  5731.     BotPostThink ();
  5732. };
  5733.  
  5734. void () bot_pain =
  5735. {
  5736.     if (self.weaponframe)
  5737.     {
  5738.         return;
  5739.     }
  5740.     if ((self.invisible_finished > time))
  5741.     {
  5742.         return;
  5743.     }
  5744.     if ((self.weapon == IT_AXE))
  5745.     {
  5746.         bot_axpain1 ();
  5747.     }
  5748.     else
  5749.     {
  5750.         bot_pain1 ();
  5751.     }
  5752. };
  5753. void () bot_diea1;
  5754. void () bot_dieb1;
  5755. void () bot_diec1;
  5756. void () bot_died1;
  5757. void () bot_diee1;
  5758. void () bot_die_ax1;
  5759.  
  5760. void () BotDead =
  5761. {
  5762.     self.nextthink = ((time + 0.3) + ((random () * (NUMBOTS + MOVETYPE_WALK)) * 0.1));
  5763.     if (teamplay)
  5764.     {
  5765.         self.nextthink = (self.nextthink + random ());
  5766.     }
  5767.     if (TELEFRAGFLAG)
  5768.     {
  5769.         self.nextthink = (self.nextthink + (MOVETYPE_FLY * random ()));
  5770.         TELEFRAGFLAG = FALSE;
  5771.     }
  5772.     self.think = respawnBot;
  5773.     self.deadflag = DEAD_DEAD;
  5774. };
  5775.  
  5776. void () BotDie =
  5777. {
  5778.     local float i;
  5779.  
  5780.     if ((self.deadflag != DEAD_NO))
  5781.     {
  5782.         return;
  5783.     }
  5784.     self.items = (self.items - (self.items & IT_INVISIBILITY));
  5785.     self.invisible_finished = FALSE;
  5786.     self.invincible_finished = FALSE;
  5787.     self.super_damage_finished = FALSE;
  5788.     self.radsuit_finished = FALSE;
  5789.     self.modelindex = modelindex_player;
  5790.     DropBackpack ();
  5791.     self.weaponmodel = "";
  5792.     self.view_ofs = '0 0 -8';
  5793.     self.deadflag = DEAD_DYING;
  5794.     self.solid = SOLID_NOT;
  5795.     self.flags = (self.flags - (self.flags & FL_ONGROUND));
  5796.     self.movetype = MOVETYPE_TOSS;
  5797.     if ((self.velocity_z < MOVETYPE_BOUNCE))
  5798.     {
  5799.         self.velocity_z = (self.velocity_z + (random () * 300));
  5800.     }
  5801.     if ((self.health < -40))
  5802.     {
  5803.         GibPlayer ();
  5804.         BotDead ();
  5805.         return;
  5806.     }
  5807.     DeathSound ();
  5808.     self.angles_x = FALSE;
  5809.     self.angles_z = FALSE;
  5810.     if ((self.weapon == IT_AXE))
  5811.     {
  5812.         bot_die_ax1 ();
  5813.         return;
  5814.     }
  5815.     i = cvar ("temp1");
  5816.     if (!i)
  5817.     {
  5818.         i = (TRUE + floor ((random () * MOVETYPE_TOSS)));
  5819.     }
  5820.     if ((i == TRUE))
  5821.     {
  5822.         bot_diea1 ();
  5823.     }
  5824.     else
  5825.     {
  5826.         if ((i == FL_SWIM))
  5827.         {
  5828.             bot_dieb1 ();
  5829.         }
  5830.         else
  5831.         {
  5832.             if ((i == MOVETYPE_WALK))
  5833.             {
  5834.                 bot_diec1 ();
  5835.             }
  5836.             else
  5837.             {
  5838.                 if ((i == MOVETYPE_STEP))
  5839.                 {
  5840.                     bot_died1 ();
  5841.                 }
  5842.                 else
  5843.                 {
  5844.                     bot_diee1 ();
  5845.                 }
  5846.             }
  5847.         }
  5848.     }
  5849. };
  5850.  
  5851. void () bot_diea1 = [ 50, bot_diea2 ]
  5852. {
  5853. };
  5854.  
  5855. void () bot_diea2 = [ 51, bot_diea3 ]
  5856. {
  5857. };
  5858.  
  5859. void () bot_diea3 = [ 52, bot_diea4 ]
  5860. {
  5861. };
  5862.  
  5863. void () bot_diea4 = [ 53, bot_diea5 ]
  5864. {
  5865. };
  5866.  
  5867. void () bot_diea5 = [ 54, bot_diea6 ]
  5868. {
  5869. };
  5870.  
  5871. void () bot_diea6 = [ 55, bot_diea7 ]
  5872. {
  5873. };
  5874.  
  5875. void () bot_diea7 = [ 56, bot_diea8 ]
  5876. {
  5877. };
  5878.  
  5879. void () bot_diea8 = [ 57, bot_diea9 ]
  5880. {
  5881. };
  5882.  
  5883. void () bot_diea9 = [ 58, bot_diea10 ]
  5884. {
  5885. };
  5886.  
  5887. void () bot_diea10 = [ 59, bot_diea11 ]
  5888. {
  5889. };
  5890.  
  5891. void () bot_diea11 = [ 60, bot_diea11 ]
  5892. {
  5893.     BotDead ();
  5894. };
  5895.  
  5896. void () bot_dieb1 = [ 61, bot_dieb2 ]
  5897. {
  5898. };
  5899.  
  5900. void () bot_dieb2 = [ 62, bot_dieb3 ]
  5901. {
  5902. };
  5903.  
  5904. void () bot_dieb3 = [ 63, bot_dieb4 ]
  5905. {
  5906. };
  5907.  
  5908. void () bot_dieb4 = [ 64, bot_dieb5 ]
  5909. {
  5910. };
  5911.  
  5912. void () bot_dieb5 = [ 65, bot_dieb6 ]
  5913. {
  5914. };
  5915.  
  5916. void () bot_dieb6 = [ 66, bot_dieb7 ]
  5917. {
  5918. };
  5919.  
  5920. void () bot_dieb7 = [ 67, bot_dieb8 ]
  5921. {
  5922. };
  5923.  
  5924. void () bot_dieb8 = [ 68, bot_dieb9 ]
  5925. {
  5926. };
  5927.  
  5928. void () bot_dieb9 = [ 69, bot_dieb9 ]
  5929. {
  5930.     BotDead ();
  5931. };
  5932.  
  5933. void () bot_diec1 = [ 70, bot_diec2 ]
  5934. {
  5935. };
  5936.  
  5937. void () bot_diec2 = [ 71, bot_diec3 ]
  5938. {
  5939. };
  5940.  
  5941. void () bot_diec3 = [ 72, bot_diec4 ]
  5942. {
  5943. };
  5944.  
  5945. void () bot_diec4 = [ 73, bot_diec5 ]
  5946. {
  5947. };
  5948.  
  5949. void () bot_diec5 = [ 74, bot_diec6 ]
  5950. {
  5951. };
  5952.  
  5953. void () bot_diec6 = [ 75, bot_diec7 ]
  5954. {
  5955. };
  5956.  
  5957. void () bot_diec7 = [ 76, bot_diec8 ]
  5958. {
  5959. };
  5960.  
  5961. void () bot_diec8 = [ 77, bot_diec9 ]
  5962. {
  5963. };
  5964.  
  5965. void () bot_diec9 = [ 78, bot_diec10 ]
  5966. {
  5967. };
  5968.  
  5969. void () bot_diec10 = [ 79, bot_diec11 ]
  5970. {
  5971. };
  5972.  
  5973. void () bot_diec11 = [ 80, bot_diec12 ]
  5974. {
  5975. };
  5976.  
  5977. void () bot_diec12 = [ 81, bot_diec13 ]
  5978. {
  5979. };
  5980.  
  5981. void () bot_diec13 = [ 82, bot_diec14 ]
  5982. {
  5983. };
  5984.  
  5985. void () bot_diec14 = [ 83, bot_diec15 ]
  5986. {
  5987. };
  5988.  
  5989. void () bot_diec15 = [ 84, bot_diec15 ]
  5990. {
  5991.     BotDead ();
  5992. };
  5993.  
  5994. void () bot_died1 = [ 85, bot_died2 ]
  5995. {
  5996. };
  5997.  
  5998. void () bot_died2 = [ 86, bot_died3 ]
  5999. {
  6000. };
  6001.  
  6002. void () bot_died3 = [ 87, bot_died4 ]
  6003. {
  6004. };
  6005.  
  6006. void () bot_died4 = [ 88, bot_died5 ]
  6007. {
  6008. };
  6009.  
  6010. void () bot_died5 = [ 89, bot_died6 ]
  6011. {
  6012. };
  6013.  
  6014. void () bot_died6 = [ 90, bot_died7 ]
  6015. {
  6016. };
  6017.  
  6018. void () bot_died7 = [ 91, bot_died8 ]
  6019. {
  6020. };
  6021.  
  6022. void () bot_died8 = [ 92, bot_died9 ]
  6023. {
  6024. };
  6025.  
  6026. void () bot_died9 = [ 93, bot_died9 ]
  6027. {
  6028.     BotDead ();
  6029. };
  6030.  
  6031. void () bot_diee1 = [ 94, bot_diee2 ]
  6032. {
  6033. };
  6034.  
  6035. void () bot_diee2 = [ 95, bot_diee3 ]
  6036. {
  6037. };
  6038.  
  6039. void () bot_diee3 = [ 96, bot_diee4 ]
  6040. {
  6041. };
  6042.  
  6043. void () bot_diee4 = [ 97, bot_diee5 ]
  6044. {
  6045. };
  6046.  
  6047. void () bot_diee5 = [ 98, bot_diee6 ]
  6048. {
  6049. };
  6050.  
  6051. void () bot_diee6 = [ 99, bot_diee7 ]
  6052. {
  6053. };
  6054.  
  6055. void () bot_diee7 = [ 100, bot_diee8 ]
  6056. {
  6057. };
  6058.  
  6059. void () bot_diee8 = [ 101, bot_diee9 ]
  6060. {
  6061. };
  6062.  
  6063. void () bot_diee9 = [ 102, bot_diee9 ]
  6064. {
  6065.     BotDead ();
  6066. };
  6067.  
  6068. void () bot_die_ax1 = [ 41, bot_die_ax2 ]
  6069. {
  6070. };
  6071.  
  6072. void () bot_die_ax2 = [ 42, bot_die_ax3 ]
  6073. {
  6074. };
  6075.  
  6076. void () bot_die_ax3 = [ 43, bot_die_ax4 ]
  6077. {
  6078. };
  6079.  
  6080. void () bot_die_ax4 = [ 44, bot_die_ax5 ]
  6081. {
  6082. };
  6083.  
  6084. void () bot_die_ax5 = [ 45, bot_die_ax6 ]
  6085. {
  6086. };
  6087.  
  6088. void () bot_die_ax6 = [ 46, bot_die_ax7 ]
  6089. {
  6090. };
  6091.  
  6092. void () bot_die_ax7 = [ 47, bot_die_ax8 ]
  6093. {
  6094. };
  6095.  
  6096. void () bot_die_ax8 = [ 48, bot_die_ax9 ]
  6097. {
  6098. };
  6099.  
  6100. void () bot_die_ax9 = [ 49, bot_die_ax9 ]
  6101. {
  6102.     BotDead ();
  6103. };
  6104.  
  6105.  
  6106. void () t_botpath =
  6107. {
  6108.     if ((other.classname != "dmbot"))
  6109.     {
  6110.         return;
  6111.     }
  6112.     if ((other.movetarget == self))
  6113.     {
  6114.         return;
  6115.     }
  6116.     bot_toucheditem ();
  6117.     addTarget (other.movetarget.movetarget, self);
  6118.     other.movetarget.movetarget = self;
  6119. };
  6120.  
  6121. entity () botpath =
  6122. {
  6123.     local entity targ;
  6124.  
  6125.     targ = spawn ();
  6126.     targ.classname = "BotPath";
  6127.     targ.solid = SOLID_TRIGGER;
  6128.     targ.movetarget = world;
  6129.     targ.touch = t_botpath;
  6130.     setsize (targ, '-4 -4 -4', '4 4 4');
  6131.     return (targ);
  6132. };
  6133.  
  6134. float (entity a, entity b) IsUpstream =
  6135. {
  6136.     if ((b.movetarget == a))
  6137.     {
  6138.         return (TRUE);
  6139.     }
  6140.     if ((b.movetarget2 == a))
  6141.     {
  6142.         return (TRUE);
  6143.     }
  6144.     if ((b.movetarget3 == a))
  6145.     {
  6146.         return (TRUE);
  6147.     }
  6148.     if ((b.movetarget4 == a))
  6149.     {
  6150.         return (TRUE);
  6151.     }
  6152.     if ((b.movetarget5 == a))
  6153.     {
  6154.         return (TRUE);
  6155.     }
  6156.     if ((b.movetarget6 == a))
  6157.     {
  6158.         return (TRUE);
  6159.     }
  6160.     return (FALSE);
  6161. };
  6162. void (entity node, entity targ, float len, entity item) cacheRouteTarget;
  6163.  
  6164. void (entity a, entity b, float recurse) updateRouteCache =
  6165. {
  6166.     RECURSEDEPTH = recurse;
  6167.     if ((b.rocketlen > FALSE))
  6168.     {
  6169.         cacheRouteTarget (b, a, b.rocketlen, b.rocketcache);
  6170.     }
  6171.     if ((b.lightninglen > FALSE))
  6172.     {
  6173.         cacheRouteTarget (b, a, b.lightninglen, b.lightningcache);
  6174.     }
  6175.     if ((b.armorlen > FALSE))
  6176.     {
  6177.         cacheRouteTarget (b, a, b.armorlen, b.armorcache);
  6178.     }
  6179.     if ((b.poweruplen > FALSE))
  6180.     {
  6181.         cacheRouteTarget (b, a, b.poweruplen, b.powerupcache);
  6182.     }
  6183.     if ((b.naillen > FALSE))
  6184.     {
  6185.         cacheRouteTarget (b, a, b.naillen, b.nailcache);
  6186.     }
  6187.     if ((b.grenadelen > FALSE))
  6188.     {
  6189.         cacheRouteTarget (b, a, b.grenadelen, b.grenadecache);
  6190.     }
  6191. };
  6192.  
  6193. void (entity a, entity b) addTarget =
  6194. {
  6195.     if ((a == b))
  6196.     {
  6197.         return;
  6198.     }
  6199.     if ((b.movetarget == a))
  6200.     {
  6201.         return;
  6202.     }
  6203.     if (!a)
  6204.     {
  6205.         return;
  6206.     }
  6207.     else
  6208.     {
  6209.         if ((b.movetarget2 == a))
  6210.         {
  6211.             updateRouteCache (a, b, FL_INWATER);
  6212.             return;
  6213.         }
  6214.         else
  6215.         {
  6216.             if ((b.movetarget3 == a))
  6217.             {
  6218.                 updateRouteCache (a, b, FL_INWATER);
  6219.                 return;
  6220.             }
  6221.             else
  6222.             {
  6223.                 if ((b.movetarget4 == a))
  6224.                 {
  6225.                     updateRouteCache (a, b, FL_INWATER);
  6226.                     return;
  6227.                 }
  6228.                 else
  6229.                 {
  6230.                     if ((b.movetarget5 == a))
  6231.                     {
  6232.                         updateRouteCache (a, b, FL_INWATER);
  6233.                         return;
  6234.                     }
  6235.                     else
  6236.                     {
  6237.                         if ((b.movetarget6 == a))
  6238.                         {
  6239.                             updateRouteCache (a, b, FL_INWATER);
  6240.                             return;
  6241.                         }
  6242.                     }
  6243.                 }
  6244.             }
  6245.         }
  6246.     }
  6247.     if (!b.movetarget)
  6248.     {
  6249.         b.movetarget = a;
  6250.     }
  6251.     else
  6252.     {
  6253.         if (!b.movetarget2)
  6254.         {
  6255.             b.movetarget2 = a;
  6256.         }
  6257.         else
  6258.         {
  6259.             if (!b.movetarget3)
  6260.             {
  6261.                 b.movetarget3 = a;
  6262.             }
  6263.             else
  6264.             {
  6265.                 if (!b.movetarget4)
  6266.                 {
  6267.                     b.movetarget4 = a;
  6268.                 }
  6269.                 else
  6270.                 {
  6271.                     if (!b.movetarget5)
  6272.                     {
  6273.                         b.movetarget5 = a;
  6274.                     }
  6275.                     else
  6276.                     {
  6277.                         if (!b.movetarget6)
  6278.                         {
  6279.                             b.movetarget6 = a;
  6280.                         }
  6281.                     }
  6282.                 }
  6283.             }
  6284.         }
  6285.     }
  6286.     updateRouteCache (a, b, MOVETYPE_BOUNCE);
  6287. };
  6288. float () FindAPath;
  6289.  
  6290. float () FindAltPath =
  6291. {
  6292.     local entity e;
  6293.     local entity carriedPath;
  6294.     local entity bestPath;
  6295.     local float dropPath;
  6296.     local float bestrng;
  6297.     local float rng;
  6298.  
  6299.     if ((self.lefty & NODROP))
  6300.     {
  6301.         self.lefty = (self.lefty - NODROP);
  6302.         return (FindAPath ());
  6303.     }
  6304.     e = findradius (self.origin, SEARCH_RADIUS);
  6305.     bestrng = 1000;
  6306.     dropPath = TRUE;
  6307.     carriedPath = self.movetarget;
  6308.     bestPath = carriedPath.movetarget;
  6309.     while (e)
  6310.     {
  6311.         if ((e.pathtype == DROPPED))
  6312.         {
  6313.             rng = vlen ((e.origin - self.origin));
  6314.             if ((rng < bestrng))
  6315.             {
  6316.                 if (BotReachable (e, self))
  6317.                 {
  6318.                     if (BotReachable (carriedPath.movetarget, e))
  6319.                     {
  6320.                         addTarget (carriedPath.movetarget, e);
  6321.                         bestPath = e;
  6322.                         bestrng = rng;
  6323.                         dropPath = FALSE;
  6324.                     }
  6325.                 }
  6326.             }
  6327.         }
  6328.         e = e.chain;
  6329.     }
  6330.     carriedPath.movetarget = bestPath;
  6331.     return (dropPath);
  6332. };
  6333.  
  6334. float () FindAPath =
  6335. {
  6336.     local float dropPath;
  6337.     local float bestrng;
  6338.     local float rng;
  6339.     local entity e;
  6340.     local entity carriedPath;
  6341.     local entity bestPath;
  6342.  
  6343.     carriedPath = self.movetarget;
  6344.     dropPath = TRUE;
  6345.     e = findradius (self.origin, SEARCH_RADIUS);
  6346.     bestrng = 1000;
  6347.     bestPath = carriedPath.movetarget;
  6348.     while (e)
  6349.     {
  6350.         if ((e.pathtype == DROPPED))
  6351.         {
  6352.             rng = vlen ((e.origin - self.origin));
  6353.             if ((rng < bestrng))
  6354.             {
  6355.                 if (BotReachable (e, self))
  6356.                 {
  6357.                     addTarget (carriedPath.movetarget, e);
  6358.                     bestPath = e;
  6359.                     bestrng = rng;
  6360.                     dropPath = FALSE;
  6361.                 }
  6362.             }
  6363.         }
  6364.         e = e.chain;
  6365.     }
  6366.     carriedPath.movetarget = bestPath;
  6367.     return (dropPath);
  6368. };
  6369.  
  6370. float () CheckDropPath =
  6371. {
  6372.     local entity carriedPath;
  6373.     local entity upstreamPath;
  6374.     local float rng;
  6375.     local float lnd;
  6376.     local float OK_HIGH;
  6377.     local string tmp;
  6378.  
  6379.     if ((NUMPATHS > 160))
  6380.     {
  6381.         return (FALSE);
  6382.     }
  6383.     carriedPath = self.movetarget;
  6384.     upstreamPath = carriedPath.movetarget;
  6385.     lnd = pointcontents (carriedPath.origin);
  6386.     if ((lnd == CONTENT_EMPTY))
  6387.     {
  6388.         rng = dropline (carriedPath.origin);
  6389.         if ((rng < (carriedPath.origin_z - SVC_FOUNDSECRET)))
  6390.         {
  6391.             if (!(carriedPath.flags & (FL_ONGROUND + FL_INWATER)))
  6392.             {
  6393.                 return (FALSE);
  6394.             }
  6395.         }
  6396.         lnd = pointcontents (((carriedPath.origin + self.mins) + '0 0 1'));
  6397.         if ((lnd != CONTENT_EMPTY))
  6398.         {
  6399.             if ((lnd != CONTENT_WATER))
  6400.             {
  6401.                 self.lefty = (self.lefty | NODROP);
  6402.                 return (FALSE);
  6403.             }
  6404.         }
  6405.     }
  6406.     else
  6407.     {
  6408.         if ((lnd != CONTENT_WATER))
  6409.         {
  6410.             self.lefty = (self.lefty | NODROP);
  6411.             return (FALSE);
  6412.         }
  6413.     }
  6414.     if (((trace_ent.classname == "plat") || (trace_ent.classname == "train")))
  6415.     {
  6416.         if (trace_ent.think)
  6417.         {
  6418.             self.lefty = (self.lefty | NODROP);
  6419.             return (FALSE);
  6420.         }
  6421.     }
  6422.     if ((self.teleport_time > time))
  6423.     {
  6424.         self.lefty = (self.lefty | NODROP);
  6425.         if ((self.teleport_time > (time + 0.5)))
  6426.         {
  6427.             return (FALSE);
  6428.         }
  6429.         if ((self.lefty & NODROP))
  6430.         {
  6431.             self.lefty = (self.lefty - NODROP);
  6432.         }
  6433.         return (FindAPath ());
  6434.     }
  6435.     if (!upstreamPath)
  6436.     {
  6437.         return (FindAPath ());
  6438.     }
  6439.     if (!BotReachable (upstreamPath, self))
  6440.     {
  6441.         if ((upstreamPath.origin_z > (self.origin_z + MAXJUMP)))
  6442.         {
  6443.             return (FindAPath ());
  6444.         }
  6445.         return (FindAltPath ());
  6446.     }
  6447.     return (FALSE);
  6448. };
  6449.  
  6450. void () NewCarriedPath =
  6451. {
  6452.     self.movetarget = botpath ();
  6453.     self.movetarget.pathtype = CARRIED;
  6454.     setorigin (self.movetarget, self.origin);
  6455. };
  6456.  
  6457. void () DropBotPath =
  6458. {
  6459.     local string tmp;
  6460.     local entity oldpath;
  6461.     local float drop;
  6462.  
  6463.     oldpath = self.movetarget;
  6464.     if (oldpath.movetarget)
  6465.     {
  6466.         if ((oldpath.origin_z > ((oldpath.movetarget.origin_z + (MAXJUMP * 0.6)) - TRUE)))
  6467.         {
  6468.             drop = (((oldpath.movetarget.origin_z - oldpath.origin_z) + (MAXJUMP * 0.6)) - TRUE);
  6469.             if ((drop < (self.mins_z + FL_SWIM)))
  6470.             {
  6471.                 drop = (self.mins_z + FL_SWIM);
  6472.             }
  6473.             oldpath.origin_z = (oldpath.origin_z + drop);
  6474.         }
  6475.     }
  6476.     NewCarriedPath ();
  6477.     oldpath.pathtype = DROPPED;
  6478.     self.movetarget.movetarget = oldpath;
  6479.     NUMPATHS = (NUMPATHS + TRUE);
  6480. };
  6481. void (entity node, float len, entity item) cacheRouteMsg;
  6482.  
  6483. void (entity node, entity targ, float len, entity item) cacheRouteTarget =
  6484. {
  6485.     local float rng;
  6486.  
  6487.     rng = vlen ((node.origin - targ.origin));
  6488.     if ((targ.pathtype == TELEPORT))
  6489.     {
  6490.         rng = 250;
  6491.     }
  6492.     rng = ((rng + len) + KINDA_WANT);
  6493.     RECURSEDEPTH = (RECURSEDEPTH + FL_SWIM);
  6494.     if ((RECURSEDEPTH < 24))
  6495.     {
  6496.         cacheRouteMsg (targ, rng, item);
  6497.     }
  6498.     else
  6499.     {
  6500.         node.endpoint = TRUE;
  6501.     }
  6502.     RECURSEDEPTH = (RECURSEDEPTH - FL_SWIM);
  6503. };
  6504.  
  6505. void (entity node, entity targ, float len, entity item) cacheRoute =
  6506. {
  6507.     RECURSEDEPTH = TRUE;
  6508.     cacheRouteTarget (node, targ, len, item);
  6509.     if ((other.classname == "dmbot"))
  6510.     {
  6511.         if ((other.rocketcache == item))
  6512.         {
  6513.             clearCache (other);
  6514.         }
  6515.         else
  6516.         {
  6517.             if ((other.lightningcache == item))
  6518.             {
  6519.                 clearCache (other);
  6520.             }
  6521.             else
  6522.             {
  6523.                 if ((other.armorcache == item))
  6524.                 {
  6525.                     clearCache (other);
  6526.                 }
  6527.                 else
  6528.                 {
  6529.                     if ((other.powerupcache == item))
  6530.                     {
  6531.                         clearCache (other);
  6532.                     }
  6533.                     else
  6534.                     {
  6535.                         if ((other.nailcache == item))
  6536.                         {
  6537.                             clearCache (other);
  6538.                         }
  6539.                         else
  6540.                         {
  6541.                             if ((other.grenadecache == item))
  6542.                             {
  6543.                                 clearCache (other);
  6544.                             }
  6545.                         }
  6546.                     }
  6547.                 }
  6548.             }
  6549.         }
  6550.     }
  6551. };
  6552.  
  6553. void (entity node, float len, entity item) cacheRouteMsg =
  6554. {
  6555.     if (item.th_cache)
  6556.     {
  6557.         if (!item.th_cache (node, len, item))
  6558.         {
  6559.             return;
  6560.         }
  6561.     }
  6562.     else
  6563.     {
  6564.         return;
  6565.     }
  6566.     if (node.movetarget)
  6567.     {
  6568.         cacheRouteTarget (node, node.movetarget, len, item);
  6569.     }
  6570.     if (node.movetarget2)
  6571.     {
  6572.         cacheRouteTarget (node, node.movetarget2, len, item);
  6573.     }
  6574.     if (node.movetarget3)
  6575.     {
  6576.         cacheRouteTarget (node, node.movetarget3, len, item);
  6577.     }
  6578.     if (node.movetarget4)
  6579.     {
  6580.         cacheRouteTarget (node, node.movetarget4, len, item);
  6581.     }
  6582.     if (node.movetarget5)
  6583.     {
  6584.         cacheRouteTarget (node, node.movetarget5, len, item);
  6585.     }
  6586.     if (node.movetarget6)
  6587.     {
  6588.         cacheRouteTarget (node, node.movetarget6, len, item);
  6589.     }
  6590. };
  6591.  
  6592. void (entity e) clearCache =
  6593. {
  6594.     e.rocketcache = world;
  6595.     e.lightningcache = world;
  6596.     e.armorcache = world;
  6597.     e.nailcache = world;
  6598.     e.grenadecache = world;
  6599.     e.powerupcache = world;
  6600.     e.rocketlen = FALSE;
  6601.     e.lightninglen = FALSE;
  6602.     e.armorlen = FALSE;
  6603.     e.naillen = FALSE;
  6604.     e.grenadelen = FALSE;
  6605.     e.poweruplen = FALSE;
  6606.     e.endpoint = FALSE;
  6607. };
  6608.  
  6609. void (entity en) RouteToEnemy =
  6610. {
  6611.     local entity e;
  6612.  
  6613.     RECURSEDEPTH = FL_CLIENT;
  6614.     e = find (world, classname, "BotPath");
  6615.     while (e)
  6616.     {
  6617.         e.enemycache = world;
  6618.         e.endpoint = FALSE;
  6619.         e = find (e, classname, "BotPath");
  6620.     }
  6621.     if (en.movetarget)
  6622.     {
  6623.         if (en.movetarget.movetarget)
  6624.         {
  6625.             cacheRouteTarget (en.movetarget, en.movetarget.movetarget, FALSE, en);
  6626.             e = find (world, classname, "BotPath");
  6627.             while (e)
  6628.             {
  6629.                 if (e.endpoint)
  6630.                 {
  6631.                     if ((e.enemycache == en))
  6632.                     {
  6633.                         RECURSEDEPTH = FL_CLIENT;
  6634.                         if (e.movetarget)
  6635.                         {
  6636.                             cacheRouteTarget (e, e.movetarget, e.enemylen, en);
  6637.                         }
  6638.                         if (e.movetarget2)
  6639.                         {
  6640.                             cacheRouteTarget (e, e.movetarget2, e.enemylen, en);
  6641.                         }
  6642.                         if (e.movetarget3)
  6643.                         {
  6644.                             cacheRouteTarget (e, e.movetarget3, e.enemylen, en);
  6645.                         }
  6646.                         if (e.movetarget4)
  6647.                         {
  6648.                             cacheRouteTarget (e, e.movetarget4, e.enemylen, en);
  6649.                         }
  6650.                         if (e.movetarget5)
  6651.                         {
  6652.                             cacheRouteTarget (e, e.movetarget5, e.enemylen, en);
  6653.                         }
  6654.                         if (e.movetarget6)
  6655.                         {
  6656.                             cacheRouteTarget (e, e.movetarget6, e.enemylen, en);
  6657.                         }
  6658.                     }
  6659.                 }
  6660.                 e = find (e, classname, "BotPath");
  6661.             }
  6662.         }
  6663.     }
  6664. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement