1 // targeted (directional) mode
2 void trigger_impulse_touch1(entity this)
8 if (this.active != ACTIVE_ACTIVE)
11 if (!isPushable(other))
16 targ = find(world, targetname, this.target);
19 objerror(this, "trigger_force without a (valid) .target!\n");
25 str = min(this.radius, vlen(this.origin - other.origin));
27 str = min(this.radius, vlen(this.origin - other.move_origin));
31 str = (str / this.radius) * this.strength;
32 else if(this.falloff == 2)
33 str = (1 - (str / this.radius)) * this.strength;
37 pushdeltatime = time - other.lastpushtime;
38 if (pushdeltatime > 0.15) pushdeltatime = 0;
39 other.lastpushtime = time;
40 if(!pushdeltatime) return;
42 if(this.spawnflags & 64)
45 float addspeed = str - other.velocity * normalize(targ.origin - this.origin);
48 float accelspeed = min(8 * pushdeltatime * str, addspeed);
49 other.velocity += accelspeed * normalize(targ.origin - this.origin);
52 float addspeed = str - other.move_velocity * normalize(targ.origin - this.origin);
55 float accelspeed = min(8 * pushdeltatime * str, addspeed);
56 other.move_velocity += accelspeed * normalize(targ.origin - this.origin);
62 other.velocity = other.velocity + normalize(targ.origin - this.origin) * str * pushdeltatime;
64 other.move_velocity = other.move_velocity + normalize(targ.origin - this.origin) * str * pushdeltatime;
68 UNSET_ONGROUND(other);
70 UpdateCSQCProjectile(other);
72 other.move_flags &= ~FL_ONGROUND;
76 // Directionless (accelerator/decelerator) mode
77 void trigger_impulse_touch2(entity this)
81 if (this.active != ACTIVE_ACTIVE)
84 if (!isPushable(other))
89 pushdeltatime = time - other.lastpushtime;
90 if (pushdeltatime > 0.15) pushdeltatime = 0;
91 other.lastpushtime = time;
92 if(!pushdeltatime) return;
94 // div0: ticrate independent, 1 = identity (not 20)
96 other.velocity = other.velocity * pow(this.strength, pushdeltatime);
98 UpdateCSQCProjectile(other);
100 other.move_velocity = other.move_velocity * pow(this.strength, pushdeltatime);
104 // Spherical (gravity/repulsor) mode
105 void trigger_impulse_touch3(entity this)
110 if (this.active != ACTIVE_ACTIVE)
113 if (!isPushable(other))
118 pushdeltatime = time - other.lastpushtime;
119 if (pushdeltatime > 0.15) pushdeltatime = 0;
120 other.lastpushtime = time;
121 if(!pushdeltatime) return;
123 setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
126 str = min(this.radius, vlen(this.origin - other.origin));
128 str = min(this.radius, vlen(this.origin - other.move_origin));
131 if(this.falloff == 1)
132 str = (1 - str / this.radius) * this.strength; // 1 in the inside
133 else if(this.falloff == 2)
134 str = (str / this.radius) * this.strength; // 0 in the inside
139 other.velocity = other.velocity + normalize(other.origin - this.origin) * str * pushdeltatime;
141 UpdateCSQCProjectile(other);
143 other.move_velocity = other.move_velocity + normalize(other.move_origin - this.origin) * str * pushdeltatime;
147 REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_IMPULSE)
149 /*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
150 -------- KEYS --------
151 target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
152 If not, this trigger acts like a damper/accelerator field.
154 strength : This is how mutch force to add in the direction of .target each second
155 when .target is set. If not, this is hoe mutch to slow down/accelerate
156 someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
158 radius : If set, act as a spherical device rather then a liniar one.
160 falloff : 0 = none, 1 = liniar, 2 = inverted liniar
162 -------- NOTES --------
163 Use a brush textured with common/origin in the trigger entity to determine the origin of the force
164 in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
167 bool trigger_impulse_send(entity this, entity to, int sf)
169 WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
171 WriteInt24_t(MSG_ENTITY, this.spawnflags);
172 WriteCoord(MSG_ENTITY, this.radius);
173 WriteCoord(MSG_ENTITY, this.strength);
174 WriteByte(MSG_ENTITY, this.falloff);
175 WriteByte(MSG_ENTITY, this.active);
177 trigger_common_write(this, true);
182 void trigger_impulse_link(entity this)
184 trigger_link(this, trigger_impulse_send);
187 spawnfunc(trigger_impulse)
189 this.active = ACTIVE_ACTIVE;
195 if(!this.strength) this.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
196 setorigin(this, this.origin);
197 setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
198 settouch(this, trigger_impulse_touch3);
204 if(!this.strength) this.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
205 settouch(this, trigger_impulse_touch1);
209 if(!this.strength) this.strength = 0.9;
210 this.strength = pow(this.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
211 settouch(this, trigger_impulse_touch2);
215 trigger_impulse_link(this);
218 NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
220 this.spawnflags = ReadInt24_t();
221 this.radius = ReadCoord();
222 this.strength = ReadCoord();
223 this.falloff = ReadByte();
224 this.active = ReadByte();
226 trigger_common_read(this, true);
229 this.classname = "trigger_impulse";
230 this.solid = SOLID_TRIGGER;
231 this.entremove = trigger_remove_generic;
232 this.move_time = time;
234 if (this.radius) { settouch(this, trigger_impulse_touch3); }
235 else if (this.target) { settouch(this, trigger_impulse_touch1); }
236 else { settouch(this, trigger_impulse_touch2); }