2 // NOTE: also contains trigger_once at bottom
5 // the wait time has passed, so set back up for another activation
6 void multi_wait(entity this)
10 SetResourceExplicit(this, RES_HEALTH, this.max_health);
11 this.takedamage = DAMAGE_YES;
12 this.solid = SOLID_BBOX;
17 // the trigger was just touched/killed/used
18 // this.enemy should be set to the activator so it can be held through a delay
19 // so wait for the delay time before firing
20 void multi_trigger(entity this)
22 if (this.nextthink > time)
24 return; // allready been triggered
27 if((this.spawnflags & ONLY_PLAYERS) && !IS_PLAYER(this.enemy))
29 return; // only players
32 // TODO: restructure this so that trigger_secret is more independent
33 if (this.classname == "trigger_secret")
35 if (!IS_PLAYER(this.enemy))
37 found_secrets = found_secrets + 1;
38 WriteByte (MSG_ALL, SVC_FOUNDSECRET);
43 _sound (this.enemy, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
46 // don't trigger again until reset
47 this.takedamage = DAMAGE_NO;
49 SUB_UseTargets(this, this.enemy, this.goalentity);
53 setthink(this, multi_wait);
54 this.nextthink = time + this.wait;
56 else if (this.wait == 0)
58 multi_wait(this); // waiting finished
61 { // we can't just delete(this) here, because this is a touch function
62 // called while C code is looping through area links...
63 settouch(this, func_null);
67 void multi_use(entity this, entity actor, entity trigger)
69 this.goalentity = trigger;
74 void multi_touch(entity this, entity toucher)
76 if(!(this.spawnflags & ALL_ENTITIES) && !toucher.iscreature)
83 if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
89 // if the trigger has an angles field, check player's facing direction
90 if (this.movedir != '0 0 0')
92 makevectors (toucher.angles);
93 if (v_forward * this.movedir < 0)
94 return; // not facing the right way
97 // if the trigger has pressed keys, check that the player is pressing those keys
98 if(this.pressedkeys && IS_PLAYER(toucher)) // only for players
100 if(!(CS(toucher).pressedkeys & this.pressedkeys))
106 EXACTTRIGGER_TOUCH(this, toucher);
108 this.enemy = toucher;
109 this.goalentity = toucher;
113 void multi_eventdamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
117 if(this.spawnflags & NOSPLASH)
118 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
121 if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != attacker.team))
123 TakeResource(this, RES_HEALTH, damage);
124 if (GetResource(this, RES_HEALTH) <= 0)
126 this.enemy = attacker;
127 this.goalentity = inflictor;
132 void multi_reset(entity this)
134 if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
135 settouch(this, multi_touch);
138 SetResourceExplicit(this, RES_HEALTH, this.max_health);
139 this.takedamage = DAMAGE_YES;
140 this.solid = SOLID_BBOX;
142 setthink(this, func_null);
144 this.team = this.team_saved;
147 /*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
148 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.
149 If "delay" is set, the trigger waits some time after activating before firing.
150 "wait" : Seconds between triggerings. (.2 default)
151 If notouch is set, the trigger is only fired by other entities, not by touching.
152 NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
158 set "message" to text string
160 spawnfunc(trigger_multiple)
162 this.reset = multi_reset;
163 if (this.sounds == 1)
164 this.noise = "misc/secret.wav";
165 else if (this.sounds == 2)
166 this.noise = strzone(SND(TALK));
167 else if (this.sounds == 3)
168 this.noise = "misc/trigger1.wav";
171 precache_sound(this.noise);
175 else if(this.wait < -1)
177 this.use = multi_use;
179 if(this.wait == -1 && autocvar_sv_q3defragcompat)
180 this.wait = 0.1; // compatibility for q3df: "instant" return
184 this.team_saved = this.team;
185 IL_PUSH(g_saved_team, this);
187 if (GetResource(this, RES_HEALTH))
189 if (this.spawnflags & SPAWNFLAG_NOTOUCH)
190 objerror (this, "health and notouch don't make sense\n");
191 this.canteamdamage = true;
192 this.max_health = GetResource(this, RES_HEALTH);
193 this.event_damage = multi_eventdamage;
194 this.takedamage = DAMAGE_YES;
195 this.solid = SOLID_BBOX;
196 setorigin(this, this.origin); // make sure it links into the world
200 if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
202 settouch(this, multi_touch);
203 setorigin(this, this.origin); // make sure it links into the world
209 /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
210 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
211 "targetname". If "health" is set, the trigger must be killed to activate.
212 If notouch is set, the trigger is only fired by other entities, not by touching.
213 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
214 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.
220 set "message" to text string
222 spawnfunc(trigger_once)
225 spawnfunc_trigger_multiple(this);