Xonotic
sv_status_effects.qc
Go to the documentation of this file.
1 #include "sv_status_effects.qh"
2 
3 METHOD(StatusEffects, m_active, bool(StatusEffects this, entity actor))
4 {
5  TC(StatusEffects, this);
6  if(!actor.statuseffects)
7  return false; // safety net
8  return (actor.statuseffects.statuseffect_flags[this.m_id] & STATUSEFFECT_FLAG_ACTIVE);
9 }
10 
11 METHOD(StatusEffects, m_tick, void(StatusEffects this, entity actor))
12 {
13  StatusEffects data = actor.statuseffects;
14  .int flg = statuseffect_flags[this.m_id];
15  int oldflag = data.(flg);
16  data.(flg) = BITSET(data.(flg), STATUSEFFECT_FLAG_PERSISTENT, this.m_persistent(this, actor));
17  if(oldflag != data.(flg))
18  StatusEffects_update(actor);
19 
20  if(data.(flg) & STATUSEFFECT_FLAG_PERSISTENT)
21  return;
22  if(time > actor.statuseffects.statuseffect_time[this.m_id])
23  {
24  this.m_remove(this, actor, STATUSEFFECT_REMOVE_TIMEOUT);
25  return;
26  }
27 }
28 
29 METHOD(StatusEffects, m_apply, void(StatusEffects this, entity actor, float eff_time, float eff_flags))
30 {
31  if(!actor.statuseffects)
32  StatusEffects_new(actor);
33 
34  eff_flags |= STATUSEFFECT_FLAG_ACTIVE; // automatically enable active flag if applied (TODO?)
35  actor.statuseffects.statuseffect_time[this.m_id] = eff_time; // TODO: add onto the existing time rather than replacing it?
36  actor.statuseffects.statuseffect_flags[this.m_id] = eff_flags;
37  StatusEffects_update(actor);
38 }
39 
40 METHOD(StatusEffects, m_remove, void(StatusEffects this, entity actor, int removal_type))
41 {
42  StatusEffects data = actor.statuseffects;
43  if(!data)
44  return;
45  // NOTE: persistent effects do not make a sound on removal, this is intended as a workaround for #2620
46  if(removal_type == STATUSEFFECT_REMOVE_NORMAL && !(data.statuseffect_flags[this.m_id] & STATUSEFFECT_FLAG_PERSISTENT) && this.m_active(this, actor))
47  sound(actor, CH_TRIGGER, this.m_sound_rm, VOL_BASE, ATTEN_NORM);
48  data.statuseffect_time[this.m_id] = 0;
49  data.statuseffect_flags[this.m_id] = 0;
50  StatusEffects_update(actor);
51 }
52 
53 MUTATOR_HOOKFUNCTION(status_effects, SV_StartFrame)
54 {
55  if(game_stopped)
56  return;
57  // TODO: explicitly only loop through entities with a valid statuseffects object
58  // NOTE: due to the way vehicles work currently, this does not function correctly! effect does not tick while inside a vehicle
59  IL_EACH(g_damagedbycontents, it.damagedbycontents,
60  {
61  if (it.move_movetype == MOVETYPE_NOCLIP || !it.statuseffects) continue;
62  StatusEffects_tick(it);
63  });
64 }
65 
66 MUTATOR_HOOKFUNCTION(status_effects, PlayerDies)
67 {
68  entity frag_target = M_ARGV(2, entity);
69 
70  StatusEffects_removeall(frag_target, STATUSEFFECT_REMOVE_NORMAL);
71 }
72 
74 {
75  entity player = M_ARGV(0, entity);
76 
77  StatusEffects_removeall(player, STATUSEFFECT_REMOVE_NORMAL); // just to get rid of the pickup sound
78  return true;
79 }
80 
81 MUTATOR_HOOKFUNCTION(status_effects, MakePlayerObserver)
82 {
83  entity player = M_ARGV(0, entity);
84 
85  // no need to network updates, as there is no statuseffects object attached
86  StatusEffects_removeall(player, STATUSEFFECT_REMOVE_NORMAL); // just to get rid of the pickup sound
87  StatusEffects_clearall(player.statuseffects_store);
88 
89  // don't delete spectatee's effects!
90  if(player.statuseffects && player.statuseffects.owner == player)
91  StatusEffects_delete(player);
92 }
93 
94 MUTATOR_HOOKFUNCTION(status_effects, reset_map_global)
95 {
96  FOREACH_CLIENT(IS_PLAYER(it) && it.statuseffects,
97  {
98  StatusEffects_removeall(it, STATUSEFFECT_REMOVE_NORMAL); // just to get rid of the pickup sound
99  StatusEffects_clearall(it.statuseffects);
100  StatusEffects_update(it);
101  });
102  return false;
103 }
104 
106 {
107  entity spectatee = M_ARGV(0, entity);
108  entity client = M_ARGV(1, entity);
109 
110  client.statuseffects = spectatee.statuseffects;
111 }
112 
114 {
115  entity player = M_ARGV(0, entity);
116 
117  if(player.statuseffects && player.statuseffects.owner == player)
118  {
119  StatusEffects_clearall(player.statuseffects);
120  StatusEffects_update(player);
121  }
122  else
123  {
124  StatusEffects_clearall(player.statuseffects_store);
125  player.statuseffects = NULL;
126  }
127 }
#define IL_EACH(this, cond, body)
void SpectateCopy(entity this, entity spectatee)
Definition: client.qc:1713
IntrusiveList g_damagedbycontents
Definition: damage.qh:155
entity() spawn
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
Effect is being removed by a function, calls regular removal mechanics.
Definition: all.qh:25
#define METHOD(cname, name, prototype)
Definition: oo.qh:257
ClientDisconnect(this)
int m_id
Definition: effect.qh:19
Effect is currently being granted passively.
Definition: all.qh:20
const int CH_TRIGGER
Definition: sound.qh:12
#define NULL
Definition: post.qh:17
const float VOL_BASE
Definition: sound.qh:36
#define TC(T, sym)
Definition: _all.inc:82
#define M_ARGV(x, type)
Definition: events.qh:17
const float ATTEN_NORM
Definition: sound.qh:30
MUTATOR_HOOKFUNCTION(status_effects, SV_StartFrame)
#define BITSET(var, mask, flag)
Definition: bits.qh:11
PutClientInServer(this)
#define sound(e, c, s, v, a)
Definition: sound.qh:52
float time
Definition: csprogsdefs.qc:16
#define IS_PLAYER(v)
Definition: utils.qh:9