1 // targeted (directional) mode
2 void trigger_impulse_touch1()
8 if (self.active != ACTIVE_ACTIVE)
11 if (!isPushable(other))
16 targ = find(world, targetname, self.target);
19 objerror("trigger_force without a (valid) .target!\n");
24 str = min(self.radius, vlen(self.origin - other.origin));
27 str = (str / self.radius) * self.strength;
28 else if(self.falloff == 2)
29 str = (1 - (str / self.radius)) * self.strength;
33 pushdeltatime = time - other.lastpushtime;
34 if (pushdeltatime > 0.15) pushdeltatime = 0;
35 other.lastpushtime = time;
36 if(!pushdeltatime) return;
38 if(self.spawnflags & 64)
40 float addspeed = str - other.velocity * normalize(targ.origin - self.origin);
43 float accelspeed = min(8 * pushdeltatime * str, addspeed);
44 other.velocity += accelspeed * normalize(targ.origin - self.origin);
48 other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
49 other.flags &= ~FL_ONGROUND;
51 UpdateCSQCProjectile(other);
55 // Directionless (accelerator/decelerator) mode
56 void trigger_impulse_touch2()
60 if (self.active != ACTIVE_ACTIVE)
63 if (!isPushable(other))
68 pushdeltatime = time - other.lastpushtime;
69 if (pushdeltatime > 0.15) pushdeltatime = 0;
70 other.lastpushtime = time;
71 if(!pushdeltatime) return;
73 // div0: ticrate independent, 1 = identity (not 20)
74 other.velocity = other.velocity * pow(self.strength, pushdeltatime);
76 UpdateCSQCProjectile(other);
80 // Spherical (gravity/repulsor) mode
81 void trigger_impulse_touch3()
86 if (self.active != ACTIVE_ACTIVE)
89 if (!isPushable(other))
94 pushdeltatime = time - other.lastpushtime;
95 if (pushdeltatime > 0.15) pushdeltatime = 0;
96 other.lastpushtime = time;
97 if(!pushdeltatime) return;
99 setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
101 str = min(self.radius, vlen(self.origin - other.origin));
103 if(self.falloff == 1)
104 str = (1 - str / self.radius) * self.strength; // 1 in the inside
105 else if(self.falloff == 2)
106 str = (str / self.radius) * self.strength; // 0 in the inside
110 other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
112 UpdateCSQCProjectile(other);
116 /*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
117 -------- KEYS --------
118 target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
119 If not, this trigger acts like a damper/accelerator field.
121 strength : This is how mutch force to add in the direction of .target each second
122 when .target is set. If not, this is hoe mutch to slow down/accelerate
123 someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
125 radius : If set, act as a spherical device rather then a liniar one.
127 falloff : 0 = none, 1 = liniar, 2 = inverted liniar
129 -------- NOTES --------
130 Use a brush textured with common/origin in the trigger entity to determine the origin of the force
131 in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
134 bool trigger_impulse_send(entity to, int sf)
136 WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
138 WriteCoord(MSG_ENTITY, self.radius);
139 WriteCoord(MSG_ENTITY, self.strength);
140 WriteByte(MSG_ENTITY, self.falloff);
141 WriteByte(MSG_ENTITY, self.active);
143 trigger_common_write(true);
148 void trigger_impulse_link()
150 //Net_LinkEntity(self, 0, false, trigger_impulse_send);
153 spawnfunc(trigger_impulse)
155 self.active = ACTIVE_ACTIVE;
160 if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
161 setorigin(self, self.origin);
162 setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
163 self.touch = trigger_impulse_touch3;
169 if(!self.strength) self.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
170 self.touch = trigger_impulse_touch1;
174 if(!self.strength) self.strength = 0.9;
175 self.strength = pow(self.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
176 self.touch = trigger_impulse_touch2;
180 trigger_impulse_link();
183 void ent_trigger_impulse()
185 self.radius = ReadCoord();
186 self.strength = ReadCoord();
187 self.falloff = ReadByte();
188 self.active = ReadByte();
190 trigger_common_read(true);
193 self.classname = "trigger_impulse";
194 self.solid = SOLID_TRIGGER;
195 self.entremove = trigger_remove_generic;
196 self.draw = trigger_draw_generic;
197 self.drawmask = MASK_NORMAL;
198 self.move_time = time;
200 if(self.radius) { self.trigger_touch = trigger_impulse_touch3; }
201 else if(self.target) { self.trigger_touch = trigger_impulse_touch1; }
202 else { self.trigger_touch = trigger_impulse_touch2; }