]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/trigger/multi.qc
Network impulse triggers
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / trigger / multi.qc
1 // NOTE: also contains trigger_once at bottom
2
3 #ifdef SVQC
4 // the wait time has passed, so set back up for another activation
5 void multi_wait()
6 {
7         if (self.max_health)
8         {
9                 self.health = self.max_health;
10                 self.takedamage = DAMAGE_YES;
11                 self.solid = SOLID_BBOX;
12         }
13 }
14
15
16 // the trigger was just touched/killed/used
17 // self.enemy should be set to the activator so it can be held through a delay
18 // so wait for the delay time before firing
19 void multi_trigger()
20 {
21         if (self.nextthink > time)
22         {
23                 return;         // allready been triggered
24         }
25
26         if (self.classname == "trigger_secret")
27         {
28                 if (!IS_PLAYER(self.enemy))
29                         return;
30                 found_secrets = found_secrets + 1;
31                 WriteByte (MSG_ALL, SVC_FOUNDSECRET);
32         }
33
34         if (self.noise)
35                 sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
36
37 // don't trigger again until reset
38         self.takedamage = DAMAGE_NO;
39
40         activator = self.enemy;
41         other = self.goalentity;
42         SUB_UseTargets();
43
44         if (self.wait > 0)
45         {
46                 self.think = multi_wait;
47                 self.nextthink = time + self.wait;
48         }
49         else if (self.wait == 0)
50         {
51                 multi_wait(); // waiting finished
52         }
53         else
54         {       // we can't just remove (self) here, because this is a touch function
55                 // called wheil C code is looping through area links...
56                 self.touch = func_null;
57         }
58 }
59
60 void multi_use()
61 {
62         self.goalentity = other;
63         self.enemy = activator;
64         multi_trigger();
65 }
66
67 void multi_touch()
68 {
69         if(!(self.spawnflags & 2))
70         if(!other.iscreature)
71                         return;
72
73         if(self.team)
74                 if(((self.spawnflags & 4) == 0) == (self.team != other.team))
75                         return;
76
77 // if the trigger has an angles field, check player's facing direction
78         if (self.movedir != '0 0 0')
79         {
80                 makevectors (other.angles);
81                 if (v_forward * self.movedir < 0)
82                         return;         // not facing the right way
83         }
84
85         EXACTTRIGGER_TOUCH;
86
87         self.enemy = other;
88         self.goalentity = other;
89         multi_trigger ();
90 }
91
92 void multi_eventdamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
93 {
94         if (!self.takedamage)
95                 return;
96         if(self.spawnflags & DOOR_NOSPLASH)
97                 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
98                         return;
99         self.health = self.health - damage;
100         if (self.health <= 0)
101         {
102                 self.enemy = attacker;
103                 self.goalentity = inflictor;
104                 multi_trigger();
105         }
106 }
107
108 void multi_reset()
109 {
110         if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
111                 self.touch = multi_touch;
112         if (self.max_health)
113         {
114                 self.health = self.max_health;
115                 self.takedamage = DAMAGE_YES;
116                 self.solid = SOLID_BBOX;
117         }
118         self.think = func_null;
119         self.nextthink = 0;
120         self.team = self.team_saved;
121 }
122
123 /*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
124 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.
125 If "delay" is set, the trigger waits some time after activating before firing.
126 "wait" : Seconds between triggerings. (.2 default)
127 If notouch is set, the trigger is only fired by other entities, not by touching.
128 NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
129 sounds
130 1)      secret
131 2)      beep beep
132 3)      large switch
133 4)
134 set "message" to text string
135 */
136 void spawnfunc_trigger_multiple()
137 {
138         self.reset = multi_reset;
139         if (self.sounds == 1)
140         {
141                 precache_sound ("misc/secret.wav");
142                 self.noise = "misc/secret.wav";
143         }
144         else if (self.sounds == 2)
145         {
146                 precache_sound ("misc/talk.wav");
147                 self.noise = "misc/talk.wav";
148         }
149         else if (self.sounds == 3)
150         {
151                 precache_sound ("misc/trigger1.wav");
152                 self.noise = "misc/trigger1.wav";
153         }
154
155         if (!self.wait)
156                 self.wait = 0.2;
157         else if(self.wait < -1)
158                 self.wait = 0;
159         self.use = multi_use;
160
161         EXACTTRIGGER_INIT;
162
163         self.team_saved = self.team;
164
165         if (self.health)
166         {
167                 if (self.spawnflags & SPAWNFLAG_NOTOUCH)
168                         objerror ("health and notouch don't make sense\n");
169                 self.max_health = self.health;
170                 self.event_damage = multi_eventdamage;
171                 self.takedamage = DAMAGE_YES;
172                 self.solid = SOLID_BBOX;
173                 setorigin (self, self.origin);  // make sure it links into the world
174         }
175         else
176         {
177                 if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
178                 {
179                         self.touch = multi_touch;
180                         setorigin (self, self.origin);  // make sure it links into the world
181                 }
182         }
183 }
184
185
186 /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
187 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
188 "targetname".  If "health" is set, the trigger must be killed to activate.
189 If notouch is set, the trigger is only fired by other entities, not by touching.
190 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
191 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.
192 sounds
193 1)      secret
194 2)      beep beep
195 3)      large switch
196 4)
197 set "message" to text string
198 */
199 void spawnfunc_trigger_once()
200 {
201         self.wait = -1;
202         spawnfunc_trigger_multiple();
203 }
204 #endif