g_rogue_newtrig.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. // g_newtrig.c
  4. // pmack
  5. // october 1997
  6. #include "../g_local.h"
  7. /*QUAKED info_teleport_destination (.5 .5 .5) (-16 -16 -24) (16 16 32)
  8. Destination marker for a teleporter.
  9. */
  10. void SP_info_teleport_destination(edict_t *self)
  11. {
  12. }
  13. // unused; broken?
  14. // constexpr uint32_t SPAWNFLAG_TELEPORT_PLAYER_ONLY = 1;
  15. // unused
  16. // constexpr uint32_t SPAWNFLAG_TELEPORT_SILENT = 2;
  17. // unused
  18. // constexpr uint32_t SPAWNFLAG_TELEPORT_CTF_ONLY = 4;
  19. constexpr spawnflags_t SPAWNFLAG_TELEPORT_START_ON = 8_spawnflag;
  20. /*QUAKED trigger_teleport (.5 .5 .5) ? player_only silent ctf_only start_on
  21. Any object touching this will be transported to the corresponding
  22. info_teleport_destination entity. You must set the "target" field,
  23. and create an object with a "targetname" field that matches.
  24. If the trigger_teleport has a targetname, it will only teleport
  25. entities when it has been fired.
  26. player_only: only players are teleported
  27. silent: <not used right now>
  28. ctf_only: <not used right now>
  29. start_on: when trigger has targetname, start active, deactivate when used.
  30. */
  31. TOUCH(trigger_teleport_touch) (edict_t *self, edict_t *other, const trace_t &tr, bool other_touching_self) -> void
  32. {
  33. edict_t *dest;
  34. if (/*(self->spawnflags & SPAWNFLAG_TELEPORT_PLAYER_ONLY) &&*/ !(other->client))
  35. return;
  36. if (self->delay)
  37. return;
  38. dest = G_PickTarget(self->target);
  39. if (!dest)
  40. {
  41. gi.Com_Print("Teleport Destination not found!\n");
  42. return;
  43. }
  44. gi.WriteByte(svc_temp_entity);
  45. gi.WriteByte(TE_TELEPORT_EFFECT);
  46. gi.WritePosition(other->s.origin);
  47. gi.multicast(other->s.origin, MULTICAST_PVS, false);
  48. other->s.origin = dest->s.origin;
  49. other->s.old_origin = dest->s.origin;
  50. other->s.origin[2] += 10;
  51. // clear the velocity and hold them in place briefly
  52. other->velocity = {};
  53. if (other->client)
  54. {
  55. other->client->ps.pmove.pm_time = 160; // hold time
  56. other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;
  57. // draw the teleport splash at source and on the player
  58. other->s.event = EV_PLAYER_TELEPORT;
  59. // set angles
  60. other->client->ps.pmove.delta_angles = dest->s.angles - other->client->resp.cmd_angles;
  61. other->client->ps.viewangles = {};
  62. other->client->v_angle = {};
  63. }
  64. other->s.angles = {};
  65. gi.linkentity(other);
  66. // kill anything at the destination
  67. KillBox(other, !!other->client);
  68. // [Paril-KEX] move sphere, if we own it
  69. if (other->client && other->client->owned_sphere)
  70. {
  71. edict_t *sphere = other->client->owned_sphere;
  72. sphere->s.origin = other->s.origin;
  73. sphere->s.origin[2] = other->absmax[2];
  74. sphere->s.angles[YAW] = other->s.angles[YAW];
  75. gi.linkentity(sphere);
  76. }
  77. }
  78. USE(trigger_teleport_use) (edict_t *self, edict_t *other, edict_t *activator) -> void
  79. {
  80. if (self->delay)
  81. self->delay = 0;
  82. else
  83. self->delay = 1;
  84. }
  85. void SP_trigger_teleport(edict_t *self)
  86. {
  87. if (!self->wait)
  88. self->wait = 0.2f;
  89. self->delay = 0;
  90. if (self->targetname)
  91. {
  92. self->use = trigger_teleport_use;
  93. if (!self->spawnflags.has(SPAWNFLAG_TELEPORT_START_ON))
  94. self->delay = 1;
  95. }
  96. self->touch = trigger_teleport_touch;
  97. self->solid = SOLID_TRIGGER;
  98. self->movetype = MOVETYPE_NONE;
  99. if (self->s.angles)
  100. G_SetMovedir(self->s.angles, self->movedir);
  101. gi.setmodel(self, self->model);
  102. gi.linkentity(self);
  103. }
  104. // ***************************
  105. // TRIGGER_DISGUISE
  106. // ***************************
  107. /*QUAKED trigger_disguise (.5 .5 .5) ? TOGGLE START_ON REMOVE
  108. Anything passing through this trigger when it is active will
  109. be marked as disguised.
  110. TOGGLE - field is turned off and on when used. (Paril N.B.: always the case)
  111. START_ON - field is active when spawned.
  112. REMOVE - field removes the disguise
  113. */
  114. // unused
  115. // constexpr uint32_t SPAWNFLAG_DISGUISE_TOGGLE = 1;
  116. constexpr spawnflags_t SPAWNFLAG_DISGUISE_START_ON = 2_spawnflag;
  117. constexpr spawnflags_t SPAWNFLAG_DISGUISE_REMOVE = 4_spawnflag;
  118. TOUCH(trigger_disguise_touch) (edict_t *self, edict_t *other, const trace_t &tr, bool other_touching_self) -> void
  119. {
  120. if (other->client)
  121. {
  122. if (self->spawnflags.has(SPAWNFLAG_DISGUISE_REMOVE))
  123. other->flags &= ~FL_DISGUISED;
  124. else
  125. other->flags |= FL_DISGUISED;
  126. }
  127. }
  128. USE(trigger_disguise_use) (edict_t *self, edict_t *other, edict_t *activator) -> void
  129. {
  130. if (self->solid == SOLID_NOT)
  131. self->solid = SOLID_TRIGGER;
  132. else
  133. self->solid = SOLID_NOT;
  134. gi.linkentity(self);
  135. }
  136. void SP_trigger_disguise(edict_t *self)
  137. {
  138. if (!level.disguise_icon)
  139. level.disguise_icon = gi.imageindex("i_disguise");
  140. if (self->spawnflags.has(SPAWNFLAG_DISGUISE_START_ON))
  141. self->solid = SOLID_TRIGGER;
  142. else
  143. self->solid = SOLID_NOT;
  144. self->touch = trigger_disguise_touch;
  145. self->use = trigger_disguise_use;
  146. self->movetype = MOVETYPE_NONE;
  147. self->svflags = SVF_NOCLIENT;
  148. gi.setmodel(self, self->model);
  149. gi.linkentity(self);
  150. }