2 // targeted (directional) mode
3 void trigger_impulse_touch_directional(entity this, entity toucher)
9 if (this.active != ACTIVE_ACTIVE)
12 if (!isPushable(toucher))
15 EXACTTRIGGER_TOUCH(this, toucher);
17 targ = find(NULL, targetname, this.target);
20 objerror(this, "trigger_force without a (valid) .target!\n");
25 // falloff is not supported because radius is always 0 in directional mode
28 pushdeltatime = time - toucher.lastpushtime;
29 if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
33 toucher.lastpushtime = time;
39 if(this.spawnflags & IMPULSE_DIRECTIONAL_SPEEDTARGET)
41 float addspeed = str - toucher.velocity * normalize(targ.origin - this.origin);
44 float accelspeed = min(IMPULSE_DIRECTIONAL_MAX_ACCEL_FACTOR * pushdeltatime * str, addspeed);
45 toucher.velocity += accelspeed * normalize(targ.origin - this.origin);
49 toucher.velocity = toucher.velocity + normalize(targ.origin - this.origin) * str * pushdeltatime;
51 UNSET_ONGROUND(toucher);
54 UpdateCSQCProjectile(toucher);
58 // Directionless (accelerator/decelerator) mode
59 void trigger_impulse_touch_accel(entity this, entity toucher)
63 if (this.active != ACTIVE_ACTIVE)
66 if (!isPushable(toucher))
69 EXACTTRIGGER_TOUCH(this, toucher);
71 pushdeltatime = time - toucher.lastpushtime;
72 if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
76 toucher.lastpushtime = time;
82 // div0: ticrate independent, 1 = identity (not 20)
83 toucher.velocity = toucher.velocity * (this.strength ** pushdeltatime);
86 UpdateCSQCProjectile(toucher);
90 // Spherical (gravity/repulsor) mode
91 void trigger_impulse_touch_radial(entity this, entity toucher)
96 if (this.active != ACTIVE_ACTIVE)
99 if (!isPushable(toucher))
102 EXACTTRIGGER_TOUCH(this, toucher);
104 pushdeltatime = time - toucher.lastpushtime;
105 if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
109 toucher.lastpushtime = time;
115 setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
117 str = min(this.radius, vlen(this.origin - toucher.origin));
119 if(this.falloff == FALLOFF_LINEAR)
120 str = (1 - str / this.radius) * this.strength; // 1 in the inside
121 else if(this.falloff == FALLOFF_LINEAR_INV)
122 str = (str / this.radius) * this.strength; // 0 in the inside
126 toucher.velocity = toucher.velocity + normalize(toucher.origin - this.origin) * str * pushdeltatime;
129 UpdateCSQCProjectile(toucher);
133 REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_IMPULSE)
135 /*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
137 -------- KEYS --------
138 target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
139 If not, this trigger acts like a damper/accelerator field.
141 strength : This is how much force to add in the direction of .target each second
142 when .target is set. If not, this is how much to slow down/accelerate
143 something cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
145 radius : If set, act as a spherical device rather then a linear one.
147 falloff : 0 = none, 1 = liniar, 2 = inverted liniar
149 -------- NOTES --------
150 Use a brush textured with common/origin in the trigger entity to determine the origin of the force
151 in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
154 bool trigger_impulse_send(entity this, entity to, int sf)
156 WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
158 WriteByte(MSG_ENTITY, this.spawnflags);
159 WriteCoord(MSG_ENTITY, this.radius);
160 WriteCoord(MSG_ENTITY, this.strength);
161 WriteByte(MSG_ENTITY, this.falloff);
162 WriteByte(MSG_ENTITY, this.active);
164 trigger_common_write(this, true);
169 void trigger_impulse_link(entity this)
171 trigger_link(this, trigger_impulse_send);
174 spawnfunc(trigger_impulse)
176 this.active = ACTIVE_ACTIVE;
184 this.strength = IMPULSE_DEFAULT_RADIAL_STRENGTH * autocvar_g_triggerimpulse_radial_multiplier;
186 setorigin(this, this.origin);
187 setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
188 settouch(this, trigger_impulse_touch_radial);
196 this.strength = IMPULSE_DEFAULT_DIRECTIONAL_STRENGTH * autocvar_g_triggerimpulse_directional_multiplier;
198 settouch(this, trigger_impulse_touch_directional);
204 this.strength = IMPULSE_DEFAULT_ACCEL_STRENGTH;
206 this.strength = (this.strength ** autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
207 settouch(this, trigger_impulse_touch_accel);
211 trigger_impulse_link(this);
214 NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
216 this.spawnflags = ReadByte();
217 this.radius = ReadCoord();
218 this.strength = ReadCoord();
219 this.falloff = ReadByte();
220 this.active = ReadByte();
222 trigger_common_read(this, true);
225 this.classname = "trigger_impulse";
226 this.solid = SOLID_TRIGGER;
227 this.entremove = trigger_remove_generic;
228 this.move_time = time;
232 settouch(this, trigger_impulse_touch_radial);
234 else if (this.target)
236 settouch(this, trigger_impulse_touch_directional);
240 settouch(this, trigger_impulse_touch_accel);