g_xatrix_func.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. #include "../g_local.h"
  4. /*QUAKED rotating_light (0 .5 .8) (-8 -8 -8) (8 8 8) START_OFF ALARM
  5. "health" if set, the light may be killed.
  6. */
  7. // RAFAEL
  8. // note to self
  9. // the lights will take damage from explosions
  10. // this could leave a player in total darkness very bad
  11. constexpr spawnflags_t SPAWNFLAG_ROTATING_LIGHT_START_OFF = 1_spawnflag;
  12. constexpr spawnflags_t SPAWNFLAG_ROTATING_LIGHT_ALARM = 2_spawnflag;
  13. THINK(rotating_light_alarm) (edict_t *self) -> void
  14. {
  15. if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_START_OFF))
  16. {
  17. self->think = nullptr;
  18. self->nextthink = 0_ms;
  19. }
  20. else
  21. {
  22. gi.sound(self, CHAN_NO_PHS_ADD | CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0);
  23. self->nextthink = level.time + 1_sec;
  24. }
  25. }
  26. DIE(rotating_light_killed) (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, const vec3_t &point, const mod_t &mod) -> void
  27. {
  28. gi.WriteByte(svc_temp_entity);
  29. gi.WriteByte(TE_WELDING_SPARKS);
  30. gi.WriteByte(30);
  31. gi.WritePosition(self->s.origin);
  32. gi.WriteDir(vec3_origin);
  33. gi.WriteByte(irandom(0xe0, 0xe8));
  34. gi.multicast(self->s.origin, MULTICAST_PVS, false);
  35. self->s.effects &= ~EF_SPINNINGLIGHTS;
  36. self->use = nullptr;
  37. self->think = G_FreeEdict;
  38. self->nextthink = level.time + FRAME_TIME_S;
  39. }
  40. USE(rotating_light_use) (edict_t *self, edict_t *other, edict_t *activator) -> void
  41. {
  42. if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_START_OFF))
  43. {
  44. self->spawnflags &= ~SPAWNFLAG_ROTATING_LIGHT_START_OFF;
  45. self->s.effects |= EF_SPINNINGLIGHTS;
  46. if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_ALARM))
  47. {
  48. self->think = rotating_light_alarm;
  49. self->nextthink = level.time + FRAME_TIME_S;
  50. }
  51. }
  52. else
  53. {
  54. self->spawnflags |= SPAWNFLAG_ROTATING_LIGHT_START_OFF;
  55. self->s.effects &= ~EF_SPINNINGLIGHTS;
  56. }
  57. }
  58. void SP_rotating_light(edict_t *self)
  59. {
  60. self->movetype = MOVETYPE_STOP;
  61. self->solid = SOLID_BBOX;
  62. self->s.modelindex = gi.modelindex("models/objects/light/tris.md2");
  63. self->s.frame = 0;
  64. self->use = rotating_light_use;
  65. if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_START_OFF))
  66. self->s.effects &= ~EF_SPINNINGLIGHTS;
  67. else
  68. {
  69. self->s.effects |= EF_SPINNINGLIGHTS;
  70. }
  71. if (!self->speed)
  72. self->speed = 32;
  73. // this is a real cheap way
  74. // to set the radius of the light
  75. // self->s.frame = self->speed;
  76. if (!self->health)
  77. {
  78. self->health = 10;
  79. self->max_health = self->health;
  80. self->die = rotating_light_killed;
  81. self->takedamage = true;
  82. }
  83. else
  84. {
  85. self->max_health = self->health;
  86. self->die = rotating_light_killed;
  87. self->takedamage = true;
  88. }
  89. if (self->spawnflags.has(SPAWNFLAG_ROTATING_LIGHT_ALARM))
  90. {
  91. self->moveinfo.sound_start = gi.soundindex("misc/alarm.wav");
  92. }
  93. gi.linkentity(self);
  94. }
  95. /*QUAKED func_object_repair (1 .5 0) (-8 -8 -8) (8 8 8)
  96. object to be repaired.
  97. The default delay is 1 second
  98. "delay" the delay in seconds for spark to occur
  99. */
  100. THINK(object_repair_fx) (edict_t *ent) -> void
  101. {
  102. ent->nextthink = level.time + gtime_t::from_sec(ent->delay);
  103. if (ent->health <= 100)
  104. ent->health++;
  105. else
  106. {
  107. gi.WriteByte(svc_temp_entity);
  108. gi.WriteByte(TE_WELDING_SPARKS);
  109. gi.WriteByte(10);
  110. gi.WritePosition(ent->s.origin);
  111. gi.WriteDir(vec3_origin);
  112. gi.WriteByte(irandom(0xe0, 0xe8));
  113. gi.multicast(ent->s.origin, MULTICAST_PVS, false);
  114. }
  115. }
  116. THINK(object_repair_dead) (edict_t *ent) -> void
  117. {
  118. G_UseTargets(ent, ent);
  119. ent->nextthink = level.time + 10_hz;
  120. ent->think = object_repair_fx;
  121. }
  122. THINK(object_repair_sparks) (edict_t *ent) -> void
  123. {
  124. if (ent->health <= 0)
  125. {
  126. ent->nextthink = level.time + 10_hz;
  127. ent->think = object_repair_dead;
  128. return;
  129. }
  130. ent->nextthink = level.time + gtime_t::from_sec(ent->delay);
  131. gi.WriteByte(svc_temp_entity);
  132. gi.WriteByte(TE_WELDING_SPARKS);
  133. gi.WriteByte(10);
  134. gi.WritePosition(ent->s.origin);
  135. gi.WriteDir(vec3_origin);
  136. gi.WriteByte(irandom(0xe0, 0xe8));
  137. gi.multicast(ent->s.origin, MULTICAST_PVS, false);
  138. }
  139. void SP_object_repair(edict_t *ent)
  140. {
  141. ent->movetype = MOVETYPE_NONE;
  142. ent->solid = SOLID_BBOX;
  143. ent->classname = "object_repair";
  144. ent->mins = { -8, -8, 8 };
  145. ent->maxs = { 8, 8, 8 };
  146. ent->think = object_repair_sparks;
  147. ent->nextthink = level.time + 1_sec;
  148. ent->health = 100;
  149. if (!ent->delay)
  150. ent->delay = 1.0;
  151. }