g_newtarg.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. #include "g_local.h"
  4. //==========================================================
  5. /*QUAKED target_steam (1 0 0) (-8 -8 -8) (8 8 8)
  6. Creates a steam effect (particles w/ velocity in a line).
  7. speed = velocity of particles (default 50)
  8. count = number of particles (default 32)
  9. sounds = color of particles (default 8 for steam)
  10. the color range is from this color to this color + 6
  11. wait = seconds to run before stopping (overrides default
  12. value derived from func_timer)
  13. best way to use this is to tie it to a func_timer that "pokes"
  14. it every second (or however long you set the wait time, above)
  15. note that the width of the base is proportional to the speed
  16. good colors to use:
  17. 6-9 - varying whites (darker to brighter)
  18. 224 - sparks
  19. 176 - blue water
  20. 80 - brown water
  21. 208 - slime
  22. 232 - blood
  23. */
  24. void use_target_steam (edict_t *self, edict_t *other, edict_t *activator)
  25. {
  26. // FIXME - this needs to be a global
  27. static int nextid;
  28. vec3_t point;
  29. if (nextid > 20000)
  30. nextid = nextid %20000;
  31. nextid++;
  32. // automagically set wait from func_timer unless they set it already, or
  33. // default to 1000 if not called by a func_timer (eek!)
  34. if (!self->wait)
  35. if (other)
  36. self->wait = other->wait * 1000;
  37. else
  38. self->wait = 1000;
  39. if (self->enemy)
  40. {
  41. VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point);
  42. VectorSubtract (point, self->s.origin, self->movedir);
  43. VectorNormalize (self->movedir);
  44. }
  45. VectorMA (self->s.origin, self->plat2flags*0.5, self->movedir, point);
  46. if (self->wait > 100)
  47. {
  48. gi.WriteByte (svc_temp_entity);
  49. gi.WriteByte (TE_STEAM);
  50. gi.WriteShort (nextid);
  51. gi.WriteByte (self->count);
  52. gi.WritePosition (self->s.origin);
  53. gi.WriteDir (self->movedir);
  54. gi.WriteByte (self->sounds&0xff);
  55. gi.WriteShort ( (short int)(self->plat2flags) );
  56. gi.WriteLong ( (int)(self->wait) );
  57. gi.multicast (self->s.origin, MULTICAST_PVS);
  58. }
  59. else
  60. {
  61. gi.WriteByte (svc_temp_entity);
  62. gi.WriteByte (TE_STEAM);
  63. gi.WriteShort ((short int)-1);
  64. gi.WriteByte (self->count);
  65. gi.WritePosition (self->s.origin);
  66. gi.WriteDir (self->movedir);
  67. gi.WriteByte (self->sounds&0xff);
  68. gi.WriteShort ( (short int)(self->plat2flags) );
  69. gi.multicast (self->s.origin, MULTICAST_PVS);
  70. }
  71. }
  72. void target_steam_start (edict_t *self)
  73. {
  74. edict_t *ent;
  75. self->use = use_target_steam;
  76. if (self->target)
  77. {
  78. ent = G_Find (NULL, FOFS(targetname), self->target);
  79. if (!ent)
  80. gi.dprintf ("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target);
  81. self->enemy = ent;
  82. }
  83. else
  84. {
  85. G_SetMovedir (self->s.angles, self->movedir);
  86. }
  87. if (!self->count)
  88. self->count = 32;
  89. if (!self->plat2flags)
  90. self->plat2flags = 75;
  91. if (!self->sounds)
  92. self->sounds = 8;
  93. if (self->wait)
  94. self->wait *= 1000; // we want it in milliseconds, not seconds
  95. // paranoia is good
  96. self->sounds &= 0xff;
  97. self->count &= 0xff;
  98. self->svflags = SVF_NOCLIENT;
  99. gi.linkentity (self);
  100. }
  101. void SP_target_steam (edict_t *self)
  102. {
  103. self->plat2flags = self->speed;
  104. if (self->target)
  105. {
  106. self->think = target_steam_start;
  107. self->nextthink = level.time + 1;
  108. }
  109. else
  110. target_steam_start (self);
  111. }
  112. //==========================================================
  113. // target_anger
  114. //==========================================================
  115. void target_anger_use (edict_t *self, edict_t *other, edict_t *activator)
  116. {
  117. edict_t *target;
  118. edict_t *t;
  119. t = NULL;
  120. target = G_Find (t, FOFS(targetname), self->killtarget);
  121. if (target && self->target)
  122. {
  123. // Make whatever a "good guy" so the monster will try to kill it!
  124. target->monsterinfo.aiflags |= AI_GOOD_GUY;
  125. target->svflags |= SVF_MONSTER;
  126. target->health = 300;
  127. t = NULL;
  128. while ((t = G_Find (t, FOFS(targetname), self->target)))
  129. {
  130. if (t == self)
  131. {
  132. gi.dprintf ("WARNING: entity used itself.\n");
  133. }
  134. else
  135. {
  136. if (t->use)
  137. {
  138. if (t->health < 0)
  139. {
  140. // if ((g_showlogic) && (g_showlogic->value))
  141. // gi.dprintf ("target_anger with dead monster!\n");
  142. return;
  143. }
  144. t->enemy = target;
  145. t->monsterinfo.aiflags |= AI_TARGET_ANGER;
  146. FoundTarget (t);
  147. }
  148. }
  149. if (!self->inuse)
  150. {
  151. gi.dprintf("entity was removed while using targets\n");
  152. return;
  153. }
  154. }
  155. }
  156. }
  157. /*QUAKED target_anger (1 0 0) (-8 -8 -8) (8 8 8)
  158. This trigger will cause an entity to be angry at another entity when a player touches it. Target the
  159. entity you want to anger, and killtarget the entity you want it to be angry at.
  160. target - entity to piss off
  161. killtarget - entity to be pissed off at
  162. */
  163. void SP_target_anger (edict_t *self)
  164. {
  165. if (!self->target)
  166. {
  167. gi.dprintf("target_anger without target!\n");
  168. G_FreeEdict (self);
  169. return;
  170. }
  171. if (!self->killtarget)
  172. {
  173. gi.dprintf("target_anger without killtarget!\n");
  174. G_FreeEdict (self);
  175. return;
  176. }
  177. self->use = target_anger_use;
  178. self->svflags = SVF_NOCLIENT;
  179. }
  180. // ================
  181. // target_spawn
  182. // ================
  183. /*
  184. extern edict_t *CreateMonster(vec3_t origin, vec3_t angles, char *classname);
  185. void target_spawn_use (edict_t *self, edict_t *other, edict_t *activator)
  186. {
  187. edict_t *newEnt;
  188. newEnt = CreateMonster (self->s.origin, self->s.angles, "monster_infantry");
  189. if(newEnt)
  190. newEnt->enemy = other;
  191. }
  192. */
  193. /*Q U AKED target_spawn (1 0 0) (-32 -32 -24) (32 32 72)
  194. */
  195. /*
  196. void SP_target_spawn (edict_t *self)
  197. {
  198. self->use = target_spawn_use;
  199. self->svflags = SVF_NOCLIENT;
  200. }
  201. */
  202. // ***********************************
  203. // target_killplayers
  204. // ***********************************
  205. void target_killplayers_use (edict_t *self, edict_t *other, edict_t *activator)
  206. {
  207. int i;
  208. edict_t *ent, *player;
  209. // kill the players
  210. for (i=0 ; i<game.maxclients ; i++)
  211. {
  212. player = &g_edicts[1+i];
  213. if (!player->inuse)
  214. continue;
  215. // nail it
  216. T_Damage (player, self, self, vec3_origin, self->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
  217. }
  218. // kill any visible monsters
  219. for (ent = g_edicts; ent < &g_edicts[globals.num_edicts] ; ent++)
  220. {
  221. if (!ent->inuse)
  222. continue;
  223. if (ent->health < 1)
  224. continue;
  225. if (!ent->takedamage)
  226. continue;
  227. for(i=0;i<game.maxclients ; i++)
  228. {
  229. player = &g_edicts[1+i];
  230. if(!player->inuse)
  231. continue;
  232. if(visible(player, ent))
  233. {
  234. T_Damage (ent, self, self, vec3_origin, ent->s.origin, vec3_origin,
  235. ent->health, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
  236. break;
  237. }
  238. }
  239. }
  240. }
  241. /*QUAKED target_killplayers (1 0 0) (-8 -8 -8) (8 8 8)
  242. When triggered, this will kill all the players on the map.
  243. */
  244. void SP_target_killplayers (edict_t *self)
  245. {
  246. self->use = target_killplayers_use;
  247. self->svflags = SVF_NOCLIENT;
  248. }
  249. /*QUAKED target_blacklight (1 0 1) (-16 -16 -24) (16 16 24)
  250. Pulsing black light with sphere in the center
  251. */
  252. void blacklight_think (edict_t *self)
  253. {
  254. self->s.angles[0] = rand()%360;
  255. self->s.angles[1] = rand()%360;
  256. self->s.angles[2] = rand()%360;
  257. self->nextthink = level.time + 0.1;
  258. }
  259. void SP_target_blacklight(edict_t *ent)
  260. {
  261. if (deathmatch->value)
  262. { // auto-remove for deathmatch
  263. G_FreeEdict (ent);
  264. return;
  265. }
  266. VectorClear (ent->mins);
  267. VectorClear (ent->maxs);
  268. ent->s.effects |= (EF_TRACKERTRAIL|EF_TRACKER);
  269. ent->think = blacklight_think;
  270. ent->s.modelindex = gi.modelindex ("models/items/spawngro2/tris.md2");
  271. ent->s.frame = 1;
  272. ent->nextthink = level.time + 0.1;
  273. gi.linkentity (ent);
  274. }
  275. /*QUAKED target_orb (1 0 1) (-16 -16 -24) (16 16 24)
  276. Translucent pulsing orb with speckles
  277. */
  278. void orb_think (edict_t *self)
  279. {
  280. self->s.angles[0] = rand()%360;
  281. self->s.angles[1] = rand()%360;
  282. self->s.angles[2] = rand()%360;
  283. // self->s.effects |= (EF_TRACKERTRAIL|EF_DOUBLE);
  284. self->nextthink = level.time + 0.1;
  285. }
  286. void SP_target_orb(edict_t *ent)
  287. {
  288. if (deathmatch->value)
  289. { // auto-remove for deathmatch
  290. G_FreeEdict (ent);
  291. return;
  292. }
  293. VectorClear (ent->mins);
  294. VectorClear (ent->maxs);
  295. // ent->s.effects |= EF_TRACKERTRAIL;
  296. ent->think = orb_think;
  297. ent->nextthink = level.time + 0.1;
  298. ent->s.modelindex = gi.modelindex ("models/items/spawngro2/tris.md2");
  299. ent->s.frame = 2;
  300. ent->s.effects |= EF_SPHERETRANS;
  301. gi.linkentity (ent);
  302. }