monsters.qc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* Copyright (C) 1996-2022 id Software LLC
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  13. See file, 'COPYING', for details.
  14. */
  15. /* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */
  16. // name =[framenum, nexttime, nextthink] {code}
  17. // expands to:
  18. // name ()
  19. // {
  20. // self.frame=framenum;
  21. // self.nextthink = time + nexttime;
  22. // self.think = nextthink
  23. // <code>
  24. // };
  25. /*
  26. ================
  27. monster_use
  28. Using a monster makes it angry at the current activator
  29. ================
  30. */
  31. void() monster_use =
  32. {
  33. if (self.enemy)
  34. return;
  35. if (self.health <= 0)
  36. return;
  37. if (activator.items & IT_INVISIBILITY)
  38. return;
  39. if (activator.flags & FL_NOTARGET)
  40. return;
  41. if (activator.classname != "player")
  42. return;
  43. // delay reaction so if the monster is teleported, its sound is still
  44. // heard
  45. self.enemy = activator;
  46. self.nextthink = time + 0.1;
  47. self.think = FoundTarget;
  48. };
  49. /*
  50. ================
  51. monster_death_use
  52. When a mosnter dies, it fires all of its targets with the current
  53. enemy as activator.
  54. ================
  55. */
  56. void() monster_death_use =
  57. {
  58. local entity ent, otemp, stemp;
  59. // fall to ground
  60. if (self.flags & FL_FLY)
  61. self.flags = self.flags - FL_FLY;
  62. if (self.flags & FL_SWIM)
  63. self.flags = self.flags - FL_SWIM;
  64. if (!self.target)
  65. return;
  66. activator = self.enemy;
  67. SUB_UseTargets ();
  68. };
  69. //============================================================================
  70. void() walkmonster_start_go =
  71. {
  72. local string stemp;
  73. local entity etemp;
  74. self.origin_z = self.origin_z + 1; // raise off floor a bit
  75. droptofloor();
  76. if (!walkmove(0,0))
  77. {
  78. dprint ("walkmonster in wall!\n");
  79. dprint (self.classname);
  80. dprint (" at ");
  81. dprint (vtos(self.origin));
  82. dprint ("\n");
  83. }
  84. self.takedamage = DAMAGE_AIM;
  85. self.ideal_yaw = self.angles * '0 1 0';
  86. if (!self.yaw_speed)
  87. self.yaw_speed = 20;
  88. self.view_ofs = '0 0 25';
  89. self.use = monster_use;
  90. self.team = TEAM_MONSTERS;
  91. self.flags = self.flags | FL_MONSTER;
  92. if (self.target)
  93. {
  94. self.goalentity = self.movetarget = find(world, targetname, self.target);
  95. self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
  96. if (!self.movetarget)
  97. {
  98. dprint ("Monster can't find target at ");
  99. dprint (vtos(self.origin));
  100. dprint ("\n");
  101. }
  102. // this used to be an objerror
  103. if (self.movetarget.classname == "path_corner")
  104. self.th_walk ();
  105. else
  106. self.pausetime = 99999999;
  107. self.th_stand ();
  108. }
  109. else
  110. {
  111. self.pausetime = 99999999;
  112. self.th_stand ();
  113. }
  114. // spread think times so they don't all happen at same time
  115. self.nextthink = self.nextthink + random()*0.5;
  116. };
  117. void() walkmonster_start =
  118. {
  119. // delay drop to floor to make sure all doors have been spawned
  120. // spread think times so they don't all happen at same time
  121. self.nextthink = self.nextthink + random()*0.5;
  122. self.think = walkmonster_start_go;
  123. total_monsters = total_monsters + 1;
  124. };
  125. void() flymonster_start_go =
  126. {
  127. self.takedamage = DAMAGE_AIM;
  128. self.ideal_yaw = self.angles * '0 1 0';
  129. if (!self.yaw_speed)
  130. self.yaw_speed = 10;
  131. self.view_ofs = '0 0 25';
  132. self.use = monster_use;
  133. self.team = TEAM_MONSTERS;
  134. self.flags = self.flags | FL_FLY;
  135. self.flags = self.flags | FL_MONSTER;
  136. if (!walkmove(0,0))
  137. {
  138. dprint ("flymonster in wall!\n");
  139. dprint (self.classname);
  140. dprint (" at ");
  141. dprint (vtos(self.origin));
  142. dprint ("\n");
  143. }
  144. if (self.target)
  145. {
  146. self.goalentity = self.movetarget = find(world, targetname, self.target);
  147. if (!self.movetarget)
  148. {
  149. dprint ("Monster can't find target at ");
  150. dprint (vtos(self.origin));
  151. dprint ("\n");
  152. }
  153. // this used to be an objerror
  154. if (self.movetarget.classname == "path_corner")
  155. self.th_walk ();
  156. else
  157. self.pausetime = 99999999;
  158. self.th_stand ();
  159. }
  160. else
  161. {
  162. self.pausetime = 99999999;
  163. self.th_stand ();
  164. }
  165. };
  166. void() flymonster_start =
  167. {
  168. // spread think times so they don't all happen at same time
  169. self.nextthink = self.nextthink + random()*0.5;
  170. self.think = flymonster_start_go;
  171. total_monsters = total_monsters + 1;
  172. };
  173. void() swimmonster_start_go =
  174. {
  175. if (deathmatch)
  176. {
  177. remove(self);
  178. return;
  179. }
  180. self.takedamage = DAMAGE_AIM;
  181. total_monsters = total_monsters + 1;
  182. self.ideal_yaw = self.angles * '0 1 0';
  183. if (!self.yaw_speed)
  184. self.yaw_speed = 10;
  185. self.view_ofs = '0 0 10';
  186. self.use = monster_use;
  187. self.team = TEAM_MONSTERS;
  188. self.flags = self.flags | FL_SWIM;
  189. self.flags = self.flags | FL_MONSTER;
  190. if (self.target)
  191. {
  192. self.goalentity = self.movetarget = find(world, targetname, self.target);
  193. if (!self.movetarget)
  194. {
  195. dprint ("Monster can't find target at ");
  196. dprint (vtos(self.origin));
  197. dprint ("\n");
  198. }
  199. // this used to be an objerror
  200. self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
  201. self.th_walk ();
  202. }
  203. else
  204. {
  205. self.pausetime = 99999999;
  206. self.th_stand ();
  207. }
  208. // spread think times so they don't all happen at same time
  209. self.nextthink = self.nextthink + random()*0.5;
  210. };
  211. void() swimmonster_start =
  212. {
  213. // spread think times so they don't all happen at same time
  214. self.nextthink = self.nextthink + random()*0.5;
  215. self.think = swimmonster_start_go;
  216. // Don't count here. swimmonster_start_go already increments
  217. // the monster count!!!
  218. // total_monsters = total_monsters + 1;
  219. };