]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/trigger/multi.qc
Merge branch 'master' into Mario/hagar_notfixed
[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 this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
103 {
104         if(!this.takedamage)
105                 return;
106         if(this.spawnflags & DOOR_NOSPLASH)
107                 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
108                         return;
109         this.health = this.health - damage;
110         if (this.health <= 0)
111         {
112                 this.enemy = attacker;
113                 this.goalentity = inflictor;
114                 WITH(entity, self, this, 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                 self.noise = "misc/secret.wav";
151         else if (self.sounds == 2)
152                 self.noise = strzone(SND(TALK));
153         else if (self.sounds == 3)
154                 self.noise = "misc/trigger1.wav";
155
156         if(self.noise)
157                 precache_sound(self.noise);
158
159         if (!self.wait)
160                 self.wait = 0.2;
161         else if(self.wait < -1)
162                 self.wait = 0;
163         self.use = multi_use;
164
165         EXACTTRIGGER_INIT;
166
167         self.team_saved = self.team;
168
169         if (self.health)
170         {
171                 if (self.spawnflags & SPAWNFLAG_NOTOUCH)
172                         objerror ("health and notouch don't make sense\n");
173                 self.max_health = self.health;
174                 self.event_damage = multi_eventdamage;
175                 self.takedamage = DAMAGE_YES;
176                 self.solid = SOLID_BBOX;
177                 setorigin (self, self.origin);  // make sure it links into the world
178         }
179         else
180         {
181                 if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
182                 {
183                         self.touch = multi_touch;
184                         setorigin (self, self.origin);  // make sure it links into the world
185                 }
186         }
187 }
188
189
190 /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
191 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
192 "targetname".  If "health" is set, the trigger must be killed to activate.
193 If notouch is set, the trigger is only fired by other entities, not by touching.
194 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
195 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.
196 sounds
197 1)      secret
198 2)      beep beep
199 3)      large switch
200 4)
201 set "message" to text string
202 */
203 spawnfunc(trigger_once)
204 {
205         this.wait = -1;
206         spawnfunc_trigger_multiple(this);
207 }
208 #endif