Xonotic
multi.qc
Go to the documentation of this file.
1 #include "multi.qh"
2 // NOTE: also contains trigger_once at bottom
3 
4 #ifdef SVQC
5 // the wait time has passed, so set back up for another activation
6 void multi_wait(entity this)
7 {
8  if (this.max_health)
9  {
11  this.takedamage = DAMAGE_YES;
12  this.solid = SOLID_BBOX;
13  }
14 }
15 
16 
17 // the trigger was just touched/killed/used
18 // this.enemy should be set to the activator so it can be held through a delay
19 // so wait for the delay time before firing
20 void multi_trigger(entity this)
21 {
22  if (this.nextthink > time)
23  {
24  return; // allready been triggered
25  }
26 
27  if((this.spawnflags & ONLY_PLAYERS) && !IS_PLAYER(this.enemy))
28  {
29  return; // only players
30  }
31 
32  if (this.noise && this.noise != "")
33  {
35  }
36 
37  // don't trigger again until reset
38  this.takedamage = DAMAGE_NO;
39 
40  SUB_UseTargets(this, this.enemy, this.goalentity);
41 
42  if (this.wait > 0)
43  {
44  setthink(this, multi_wait);
45  this.nextthink = time + this.wait;
46  }
47  else if (this.wait == 0)
48  {
49  multi_wait(this); // waiting finished
50  }
51  else
52  { // we can't just delete(this) here, because this is a touch function
53  // called while C code is looping through area links...
54  settouch(this, func_null);
55  this.use = func_null;
56  }
57 }
58 
59 void multi_use(entity this, entity actor, entity trigger)
60 {
61  this.goalentity = trigger;
62  this.enemy = actor;
63  multi_trigger(this);
64 }
65 
66 void multi_touch(entity this, entity toucher)
67 {
68  if(!(this.spawnflags & ALL_ENTITIES) && !toucher.iscreature)
69  {
70  return;
71  }
72 
73  if(this.team)
74  {
75  if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
76  {
77  return;
78  }
79  }
80 
81  // if the trigger has an angles field, check player's facing direction
82  if (this.movedir != '0 0 0')
83  {
84  makevectors (toucher.angles);
85  if (v_forward * this.movedir < 0)
86  return; // not facing the right way
87  }
88 
89  // if the trigger has pressed keys, check that the player is pressing those keys
90  if(this.pressedkeys && IS_PLAYER(toucher)) // only for players
91  {
92  if(!(CS(toucher).pressedkeys & this.pressedkeys))
93  {
94  return;
95  }
96  }
97 
98  EXACTTRIGGER_TOUCH(this, toucher);
99 
100  this.enemy = toucher;
101  this.goalentity = toucher;
102  multi_trigger(this);
103 }
104 
105 void multi_eventdamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
106 {
107  if(!this.takedamage)
108  return;
109  if(this.spawnflags & NOSPLASH)
110  if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
111  return;
112  if(this.team)
113  if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != attacker.team))
114  return;
115  TakeResource(this, RES_HEALTH, damage);
116  if (GetResource(this, RES_HEALTH) <= 0)
117  {
118  this.enemy = attacker;
119  this.goalentity = inflictor;
120  multi_trigger(this);
121  }
122 }
123 
124 void multi_reset(entity this)
125 {
126  if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
127  settouch(this, multi_touch);
128  if (this.max_health)
129  {
131  this.takedamage = DAMAGE_YES;
132  this.solid = SOLID_BBOX;
133  }
134  setthink(this, func_null);
135  this.nextthink = 0;
136  this.team = this.team_saved;
137  this.use = multi_use;
138 }
139 
140 /*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
141 Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each time.
142 If "delay" is set, the trigger waits some time after activating before firing.
143 "wait" : Seconds between triggerings. (.2 default)
144 If notouch is set, the trigger is only fired by other entities, not by touching.
145 NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
146 sounds
147 1) secret
148 2) beep beep
149 3) large switch
150 4)
151 set "message" to text string
152 */
153 spawnfunc(trigger_multiple)
154 {
155  this.reset = multi_reset;
156  if (this.sounds == 1)
157  this.noise = "misc/secret.wav";
158  else if (this.sounds == 2)
159  this.noise = strzone(SND(TALK));
160  else if (this.sounds == 3)
161  this.noise = "misc/trigger1.wav";
162 
163  if(this.noise && this.noise != "")
164  precache_sound(this.noise);
165 
166  if (!this.wait)
167  this.wait = 0.2;
168  else if(this.wait < -1)
169  this.wait = 0;
170  this.use = multi_use;
171 
172  if(this.wait == -1 && (q3compat & Q3COMPAT_DEFI))
173  this.wait = 0.1; // compatibility for q3df: "instant" return
174 
176 
177  this.team_saved = this.team;
178  IL_PUSH(g_saved_team, this);
179 
180  if (GetResource(this, RES_HEALTH))
181  {
182  if (this.spawnflags & SPAWNFLAG_NOTOUCH)
183  objerror (this, "health and notouch don't make sense\n");
184  this.canteamdamage = true;
185  this.max_health = GetResource(this, RES_HEALTH);
186  this.event_damage = multi_eventdamage;
187  this.takedamage = DAMAGE_YES;
188  this.solid = SOLID_BBOX;
189  setorigin(this, this.origin); // make sure it links into the world
190  }
191  else
192  {
193  if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
194  {
195  settouch(this, multi_touch);
196  setorigin(this, this.origin); // make sure it links into the world
197  }
198  }
199 }
200 
201 
202 /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
203 Variable sized trigger. Triggers once, then removes itself. You must set the key "target" to the name of another object in the level that has a matching
204 "targetname". If "health" is set, the trigger must be killed to activate.
205 If notouch is set, the trigger is only fired by other entities, not by touching.
206 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
207 if "angle" is set, the trigger will only fire when someone is facing the direction of the angle. Use "360" for an angle of 0.
208 sounds
209 1) secret
210 2) beep beep
211 3) large switch
212 4)
213 set "message" to text string
214 */
215 spawnfunc(trigger_once)
216 {
217  this.wait = -1;
218  spawnfunc_trigger_multiple(this);
219 }
220 #endif
const int HITTYPE_SPLASH
automatically set by RadiusDamage
Definition: all.qh:27
const int NOSPLASH
Definition: defs.qh:12
const int INVERT_TEAMS
Definition: defs.qh:10
const int SPAWNFLAG_NOTOUCH
Definition: defs.qh:17
#define SND(id)
Definition: all.qh:35
#define EXACTTRIGGER_INIT
Definition: common.qh:117
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
string noise
Definition: progsdefs.qc:209
int team
Definition: main.qh:157
int team_saved
Definition: vote.qh:68
#define EXACTTRIGGER_TOUCH(e, t)
Definition: common.qh:116
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition: triggers.qc:366
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
origin
Definition: ent_cs.qc:114
float spawnflags
Definition: progsdefs.qc:191
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
Definition: cl_resources.qc:31
const int ALL_ENTITIES
Definition: defs.qh:8
RES_HEALTH
Definition: ent_cs.qc:126
int q3compat
Definition: quake3.qh:3
vector movedir
Definition: progsdefs.qc:203
entity enemy
Definition: sv_ctf.qh:143
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define Q3COMPAT_DEFI
Definition: quake3.qh:5
const int CH_TRIGGER
Definition: sound.qh:12
bool canteamdamage
Definition: damage.qh:68
entity goalentity
Definition: progsdefs.qc:189
float wait
Definition: subs.qh:39
float max_health
const float VOL_BASE
Definition: sound.qh:36
float takedamage
Definition: progsdefs.qc:147
const float ATTEN_NORM
Definition: sound.qh:30
float nextthink
Definition: csprogsdefs.qc:121
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const int ONLY_PLAYERS
Definition: defs.qh:13
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
int pressedkeys
Definition: client.qh:76
#define _sound(e, c, s, v, a)
Definition: sound.qh:50
const float SOLID_BBOX
Definition: csprogsdefs.qc:246
IntrusiveList g_saved_team
Definition: vote.qh:77
setorigin(ent, v)
#define setthink(e, f)
float sounds
Definition: subs.qh:42
#define use
Definition: csprogsdefs.qh:50
#define DEATH_ISSPECIAL(t)
Definition: all.qh:35
float time
Definition: csprogsdefs.qc:16
#define makevectors
Definition: post.qh:21
float DAMAGE_NO
Definition: progsdefs.qc:282
#define IS_PLAYER(v)
Definition: utils.qh:9
var void func_null()
vector v_forward
Definition: csprogsdefs.qc:31
float solid
Definition: csprogsdefs.qc:99
float DAMAGE_YES
Definition: progsdefs.qc:283