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