]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/trigger/multi.qc
effectinfo: regenerate effectinfo.txt
[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 {SELFPARAM();
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 {SELFPARAM();
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 {SELFPARAM();
62         self.goalentity = other;
63         self.enemy = activator;
64         multi_trigger();
65 }
66
67 void multi_touch()
68 {SELFPARAM();
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         // if the trigger has pressed keys, check that the player is pressing those keys
86         if(self.pressedkeys)
87         if(IS_PLAYER(other)) // only for players
88         if(!(other.pressedkeys & self.pressedkeys))
89                 return;
90
91         EXACTTRIGGER_TOUCH;
92
93         self.enemy = other;
94         self.goalentity = other;
95         multi_trigger ();
96 }
97
98 void multi_eventdamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
99 {SELFPARAM();
100         if (!self.takedamage)
101                 return;
102         if(self.spawnflags & DOOR_NOSPLASH)
103                 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
104                         return;
105         self.health = self.health - damage;
106         if (self.health <= 0)
107         {
108                 self.enemy = attacker;
109                 self.goalentity = inflictor;
110                 multi_trigger();
111         }
112 }
113
114 void multi_reset()
115 {SELFPARAM();
116         if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
117                 self.touch = multi_touch;
118         if (self.max_health)
119         {
120                 self.health = self.max_health;
121                 self.takedamage = DAMAGE_YES;
122                 self.solid = SOLID_BBOX;
123         }
124         self.think = func_null;
125         self.nextthink = 0;
126         self.team = self.team_saved;
127 }
128
129 /*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
130 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.
131 If "delay" is set, the trigger waits some time after activating before firing.
132 "wait" : Seconds between triggerings. (.2 default)
133 If notouch is set, the trigger is only fired by other entities, not by touching.
134 NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
135 sounds
136 1)      secret
137 2)      beep beep
138 3)      large switch
139 4)
140 set "message" to text string
141 */
142 void spawnfunc_trigger_multiple()
143 {SELFPARAM();
144         self.reset = multi_reset;
145         if (self.sounds == 1)
146         {
147                 precache_sound ("misc/secret.wav");
148                 self.noise = "misc/secret.wav";
149         }
150         else if (self.sounds == 2)
151         {
152                 precache_sound ("misc/talk.wav");
153                 self.noise = "misc/talk.wav";
154         }
155         else if (self.sounds == 3)
156         {
157                 precache_sound ("misc/trigger1.wav");
158                 self.noise = "misc/trigger1.wav";
159         }
160
161         if (!self.wait)
162                 self.wait = 0.2;
163         else if(self.wait < -1)
164                 self.wait = 0;
165         self.use = multi_use;
166
167         EXACTTRIGGER_INIT;
168
169         self.team_saved = self.team;
170
171         if (self.health)
172         {
173                 if (self.spawnflags & SPAWNFLAG_NOTOUCH)
174                         objerror ("health and notouch don't make sense\n");
175                 self.max_health = self.health;
176                 self.event_damage = multi_eventdamage;
177                 self.takedamage = DAMAGE_YES;
178                 self.solid = SOLID_BBOX;
179                 setorigin (self, self.origin);  // make sure it links into the world
180         }
181         else
182         {
183                 if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
184                 {
185                         self.touch = multi_touch;
186                         setorigin (self, self.origin);  // make sure it links into the world
187                 }
188         }
189 }
190
191
192 /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
193 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
194 "targetname".  If "health" is set, the trigger must be killed to activate.
195 If notouch is set, the trigger is only fired by other entities, not by touching.
196 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
197 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.
198 sounds
199 1)      secret
200 2)      beep beep
201 3)      large switch
202 4)
203 set "message" to text string
204 */
205 void spawnfunc_trigger_once()
206 {SELFPARAM();
207         self.wait = -1;
208         spawnfunc_trigger_multiple();
209 }
210 #endif