1 // targeted (directional) mode
2 void trigger_impulse_touch1(entity this, entity toucher)
8 if (this.active != ACTIVE_ACTIVE)
11 if (!isPushable(toucher))
14 EXACTTRIGGER_TOUCH(this, toucher);
16 targ = find(NULL, targetname, this.target);
19 objerror(this, "trigger_force without a (valid) .target!\n");
24 str = min(this.radius, vlen(this.origin - toucher.origin));
27 str = (str / this.radius) * this.strength;
28 else if(this.falloff == 2)
29 str = (1 - (str / this.radius)) * this.strength;
33 pushdeltatime = time - toucher.lastpushtime;
34 if (pushdeltatime > 0.15) pushdeltatime = 0;
35 toucher.lastpushtime = time;
36 if(!pushdeltatime) return;
38 if(this.spawnflags & 64)
40 float addspeed = str - toucher.velocity * normalize(targ.origin - this.origin);
43 float accelspeed = min(8 * pushdeltatime * str, addspeed);
44 toucher.velocity += accelspeed * normalize(targ.origin - this.origin);
48 toucher.velocity = toucher.velocity + normalize(targ.origin - this.origin) * str * pushdeltatime;
50 UNSET_ONGROUND(toucher);
53 UpdateCSQCProjectile(toucher);
57 // Directionless (accelerator/decelerator) mode
58 void trigger_impulse_touch2(entity this, entity toucher)
62 if (this.active != ACTIVE_ACTIVE)
65 if (!isPushable(toucher))
68 EXACTTRIGGER_TOUCH(this, toucher);
70 pushdeltatime = time - toucher.lastpushtime;
71 if (pushdeltatime > 0.15) pushdeltatime = 0;
72 toucher.lastpushtime = time;
73 if(!pushdeltatime) return;
75 // div0: ticrate independent, 1 = identity (not 20)
76 toucher.velocity = toucher.velocity * pow(this.strength, pushdeltatime);
79 UpdateCSQCProjectile(toucher);
83 // Spherical (gravity/repulsor) mode
84 void trigger_impulse_touch3(entity this, entity toucher)
89 if (this.active != ACTIVE_ACTIVE)
92 if (!isPushable(toucher))
95 EXACTTRIGGER_TOUCH(this, toucher);
97 pushdeltatime = time - toucher.lastpushtime;
98 if (pushdeltatime > 0.15) pushdeltatime = 0;
99 toucher.lastpushtime = time;
100 if(!pushdeltatime) return;
102 setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
104 str = min(this.radius, vlen(this.origin - toucher.origin));
106 if(this.falloff == 1)
107 str = (1 - str / this.radius) * this.strength; // 1 in the inside
108 else if(this.falloff == 2)
109 str = (str / this.radius) * this.strength; // 0 in the inside
113 toucher.velocity = toucher.velocity + normalize(toucher.origin - this.origin) * str * pushdeltatime;
116 UpdateCSQCProjectile(toucher);
120 REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_IMPULSE)
122 /*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
123 -------- KEYS --------
124 target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
125 If not, this trigger acts like a damper/accelerator field.
127 strength : This is how mutch force to add in the direction of .target each second
128 when .target is set. If not, this is hoe mutch to slow down/accelerate
129 someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
131 radius : If set, act as a spherical device rather then a liniar one.
133 falloff : 0 = none, 1 = liniar, 2 = inverted liniar
135 -------- NOTES --------
136 Use a brush textured with common/origin in the trigger entity to determine the origin of the force
137 in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
140 bool trigger_impulse_send(entity this, entity to, int sf)
142 WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
144 WriteInt24_t(MSG_ENTITY, this.spawnflags);
145 WriteCoord(MSG_ENTITY, this.radius);
146 WriteCoord(MSG_ENTITY, this.strength);
147 WriteByte(MSG_ENTITY, this.falloff);
148 WriteByte(MSG_ENTITY, this.active);
150 trigger_common_write(this, true);
155 void trigger_impulse_link(entity this)
157 trigger_link(this, trigger_impulse_send);
160 spawnfunc(trigger_impulse)
162 this.active = ACTIVE_ACTIVE;
168 if(!this.strength) this.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
169 setorigin(this, this.origin);
170 setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
171 settouch(this, trigger_impulse_touch3);
177 if(!this.strength) this.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
178 settouch(this, trigger_impulse_touch1);
182 if(!this.strength) this.strength = 0.9;
183 this.strength = pow(this.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
184 settouch(this, trigger_impulse_touch2);
188 trigger_impulse_link(this);
191 NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
193 this.spawnflags = ReadInt24_t();
194 this.radius = ReadCoord();
195 this.strength = ReadCoord();
196 this.falloff = ReadByte();
197 this.active = ReadByte();
199 trigger_common_read(this, true);
202 this.classname = "trigger_impulse";
203 this.solid = SOLID_TRIGGER;
204 this.entremove = trigger_remove_generic;
205 this.move_time = time;
207 if (this.radius) { settouch(this, trigger_impulse_touch3); }
208 else if (this.target) { settouch(this, trigger_impulse_touch1); }
209 else { settouch(this, trigger_impulse_touch2); }