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