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 if (this.noise && this.noise != "")
34 _sound (this.enemy, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
37 // don't trigger again until reset
38 this.takedamage = DAMAGE_NO;
40 SUB_UseTargets(this, this.enemy, this.goalentity);
44 setthink(this, multi_wait);
45 this.nextthink = time + this.wait;
47 else if (this.wait == 0)
49 multi_wait(this); // waiting finished
52 { // we can't just delete(this) here, because this is a touch function
53 // called while C code is looping through area links...
54 settouch(this, func_null);
59 void multi_use(entity this, entity actor, entity trigger)
61 this.goalentity = trigger;
66 void multi_touch(entity this, entity toucher)
68 if(!(this.spawnflags & ALL_ENTITIES) && !toucher.iscreature)
75 if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
81 // if the trigger has an angles field, check player's facing direction
82 if (this.movedir != '0 0 0')
84 makevectors (toucher.angles);
85 if (v_forward * this.movedir < 0)
86 return; // not facing the right way
89 // if the trigger has pressed keys, check that the player is pressing those keys
90 if(this.pressedkeys && IS_PLAYER(toucher)) // only for players
92 if(!(CS(toucher).pressedkeys & this.pressedkeys))
98 EXACTTRIGGER_TOUCH(this, toucher);
100 this.enemy = toucher;
101 this.goalentity = toucher;
105 void multi_eventdamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
109 if(this.spawnflags & NOSPLASH)
110 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
113 if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != attacker.team))
115 TakeResource(this, RES_HEALTH, damage);
116 if (GetResource(this, RES_HEALTH) <= 0)
118 this.enemy = attacker;
119 this.goalentity = inflictor;
124 void multi_reset(entity this)
126 if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
127 settouch(this, multi_touch);
130 SetResourceExplicit(this, RES_HEALTH, this.max_health);
131 this.takedamage = DAMAGE_YES;
132 this.solid = SOLID_BBOX;
134 setthink(this, func_null);
136 this.team = this.team_saved;
137 this.use = multi_use;
140 /*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
141 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.
142 If "delay" is set, the trigger waits some time after activating before firing.
143 "wait" : Seconds between triggerings. (.2 default)
144 If notouch is set, the trigger is only fired by other entities, not by touching.
145 NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
151 set "message" to text string
153 spawnfunc(trigger_multiple)
155 this.reset = multi_reset;
156 if (this.sounds == 1)
157 this.noise = "misc/secret.wav";
158 else if (this.sounds == 2)
159 this.noise = strzone(SND(TALK));
160 else if (this.sounds == 3)
161 this.noise = "misc/trigger1.wav";
163 if(this.noise && this.noise != "")
164 precache_sound(this.noise);
168 else if(this.wait < -1)
170 this.use = multi_use;
172 if(this.wait == -1 && (q3compat & Q3COMPAT_DEFI))
173 this.wait = 0.1; // compatibility for q3df: "instant" return
177 this.team_saved = this.team;
178 IL_PUSH(g_saved_team, this);
180 if (GetResource(this, RES_HEALTH))
182 if (this.spawnflags & SPAWNFLAG_NOTOUCH)
183 objerror (this, "health and notouch don't make sense\n");
184 this.canteamdamage = true;
185 this.max_health = GetResource(this, RES_HEALTH);
186 this.event_damage = multi_eventdamage;
187 this.takedamage = DAMAGE_YES;
188 this.solid = SOLID_BBOX;
189 setorigin(this, this.origin); // make sure it links into the world
193 if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
195 settouch(this, multi_touch);
196 setorigin(this, this.origin); // make sure it links into the world
202 /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
203 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
204 "targetname". If "health" is set, the trigger must be killed to activate.
205 If notouch is set, the trigger is only fired by other entities, not by touching.
206 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
207 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.
213 set "message" to text string
215 spawnfunc(trigger_once)
218 spawnfunc_trigger_multiple(this);