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);
58 void multi_use(entity this, entity actor, entity trigger)
60 this.goalentity = trigger;
65 void multi_touch(entity this, entity toucher)
67 if(!(this.spawnflags & ALL_ENTITIES) && !toucher.iscreature)
74 if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
80 // if the trigger has an angles field, check player's facing direction
81 if (this.movedir != '0 0 0')
83 makevectors (toucher.angles);
84 if (v_forward * this.movedir < 0)
85 return; // not facing the right way
88 // if the trigger has pressed keys, check that the player is pressing those keys
89 if(this.pressedkeys && IS_PLAYER(toucher)) // only for players
91 if(!(CS(toucher).pressedkeys & this.pressedkeys))
97 EXACTTRIGGER_TOUCH(this, toucher);
100 this.goalentity = toucher;
104 void multi_eventdamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
108 if(this.spawnflags & NOSPLASH)
109 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
112 if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != attacker.team))
114 TakeResource(this, RES_HEALTH, damage);
115 if (GetResource(this, RES_HEALTH) <= 0)
117 this.enemy = attacker;
118 this.goalentity = inflictor;
123 void multi_reset(entity this)
125 if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
126 settouch(this, multi_touch);
129 SetResourceExplicit(this, RES_HEALTH, this.max_health);
130 this.takedamage = DAMAGE_YES;
131 this.solid = SOLID_BBOX;
133 setthink(this, func_null);
135 this.team = this.team_saved;
138 /*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
139 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.
140 If "delay" is set, the trigger waits some time after activating before firing.
141 "wait" : Seconds between triggerings. (.2 default)
142 If notouch is set, the trigger is only fired by other entities, not by touching.
143 NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
149 set "message" to text string
151 spawnfunc(trigger_multiple)
153 this.reset = multi_reset;
154 if (this.sounds == 1)
155 this.noise = "misc/secret.wav";
156 else if (this.sounds == 2)
157 this.noise = strzone(SND(TALK));
158 else if (this.sounds == 3)
159 this.noise = "misc/trigger1.wav";
161 if(this.noise && this.noise != "")
162 precache_sound(this.noise);
166 else if(this.wait < -1)
168 this.use = multi_use;
170 if(this.wait == -1 && autocvar_sv_q3defragcompat)
171 this.wait = 0.1; // compatibility for q3df: "instant" return
175 this.team_saved = this.team;
176 IL_PUSH(g_saved_team, this);
178 if (GetResource(this, RES_HEALTH))
180 if (this.spawnflags & SPAWNFLAG_NOTOUCH)
181 objerror (this, "health and notouch don't make sense\n");
182 this.canteamdamage = true;
183 this.max_health = GetResource(this, RES_HEALTH);
184 this.event_damage = multi_eventdamage;
185 this.takedamage = DAMAGE_YES;
186 this.solid = SOLID_BBOX;
187 setorigin(this, this.origin); // make sure it links into the world
191 if ( !(this.spawnflags & SPAWNFLAG_NOTOUCH) )
193 settouch(this, multi_touch);
194 setorigin(this, this.origin); // make sure it links into the world
200 /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
201 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
202 "targetname". If "health" is set, the trigger must be killed to activate.
203 If notouch is set, the trigger is only fired by other entities, not by touching.
204 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
205 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.
211 set "message" to text string
213 spawnfunc(trigger_once)
216 spawnfunc_trigger_multiple(this);