]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/trigger/impulse.qc
Merge branch 'master' into Mario/buff_updates
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / trigger / impulse.qc
1 // targeted (directional) mode
2 void trigger_impulse_touch1()
3 {
4         entity targ;
5         float pushdeltatime;
6         float str;
7
8         if (self.active != ACTIVE_ACTIVE)
9                 return;
10
11         if (!isPushable(other))
12                 return;
13
14         EXACTTRIGGER_TOUCH;
15
16         targ = find(world, targetname, self.target);
17         if(!targ)
18         {
19                 objerror("trigger_force without a (valid) .target!\n");
20                 remove(self);
21                 return;
22         }
23
24         str = min(self.radius, vlen(self.origin - other.origin));
25
26         if(self.falloff == 1)
27                 str = (str / self.radius) * self.strength;
28         else if(self.falloff == 2)
29                 str = (1 - (str / self.radius)) * self.strength;
30         else
31                 str = self.strength;
32
33         pushdeltatime = time - other.lastpushtime;
34         if (pushdeltatime > 0.15) pushdeltatime = 0;
35         other.lastpushtime = time;
36         if(!pushdeltatime) return;
37
38         other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
39         other.flags &= ~FL_ONGROUND;
40 #ifdef SVQC
41         UpdateCSQCProjectile(other);
42 #endif
43 }
44
45 // Directionless (accelerator/decelerator) mode
46 void trigger_impulse_touch2()
47 {
48         float pushdeltatime;
49
50         if (self.active != ACTIVE_ACTIVE)
51                 return;
52
53         if (!isPushable(other))
54                 return;
55
56         EXACTTRIGGER_TOUCH;
57
58         pushdeltatime = time - other.lastpushtime;
59         if (pushdeltatime > 0.15) pushdeltatime = 0;
60         other.lastpushtime = time;
61         if(!pushdeltatime) return;
62
63         // div0: ticrate independent, 1 = identity (not 20)
64         other.velocity = other.velocity * pow(self.strength, pushdeltatime);
65 #ifdef SVQC
66         UpdateCSQCProjectile(other);
67 #endif
68 }
69
70 // Spherical (gravity/repulsor) mode
71 void trigger_impulse_touch3()
72 {
73         float pushdeltatime;
74         float str;
75
76         if (self.active != ACTIVE_ACTIVE)
77                 return;
78
79         if (!isPushable(other))
80                 return;
81
82         EXACTTRIGGER_TOUCH;
83
84         pushdeltatime = time - other.lastpushtime;
85         if (pushdeltatime > 0.15) pushdeltatime = 0;
86         other.lastpushtime = time;
87         if(!pushdeltatime) return;
88
89         setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
90
91         str = min(self.radius, vlen(self.origin - other.origin));
92
93         if(self.falloff == 1)
94                 str = (1 - str / self.radius) * self.strength; // 1 in the inside
95         else if(self.falloff == 2)
96                 str = (str / self.radius) * self.strength; // 0 in the inside
97         else
98                 str = self.strength;
99
100         other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
101 #ifdef SVQC
102         UpdateCSQCProjectile(other);
103 #endif
104 }
105
106 /*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
107 -------- KEYS --------
108 target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
109                  If not, this trigger acts like a damper/accelerator field.
110
111 strength : This is how mutch force to add in the direction of .target each second
112                    when .target is set. If not, this is hoe mutch to slow down/accelerate
113                    someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
114
115 radius   : If set, act as a spherical device rather then a liniar one.
116
117 falloff : 0 = none, 1 = liniar, 2 = inverted liniar
118
119 -------- NOTES --------
120 Use a brush textured with common/origin in the trigger entity to determine the origin of the force
121 in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
122 */
123 #ifdef SVQC
124 bool trigger_impulse_send(entity to, int sf)
125 {
126         WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
127
128         WriteCoord(MSG_ENTITY, self.radius);
129         WriteCoord(MSG_ENTITY, self.strength);
130         WriteByte(MSG_ENTITY, self.falloff);
131         WriteByte(MSG_ENTITY, self.active);
132
133         trigger_common_write(true);
134
135         return true;
136 }
137
138 void trigger_impulse_link()
139 {
140         //Net_LinkEntity(self, 0, false, trigger_impulse_send);
141 }
142
143 void spawnfunc_trigger_impulse()
144 {
145         self.active = ACTIVE_ACTIVE;
146
147         EXACTTRIGGER_INIT;
148         if(self.radius)
149         {
150                 if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
151                 setorigin(self, self.origin);
152                 setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
153                 self.touch = trigger_impulse_touch3;
154         }
155         else
156         {
157                 if(self.target)
158                 {
159                         if(!self.strength) self.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
160                         self.touch = trigger_impulse_touch1;
161                 }
162                 else
163                 {
164                         if(!self.strength) self.strength = 0.9;
165                         self.strength = pow(self.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
166                         self.touch = trigger_impulse_touch2;
167                 }
168         }
169
170         trigger_impulse_link();
171 }
172 #elif defined(CSQC)
173 void ent_trigger_impulse()
174 {
175         self.radius = ReadCoord();
176         self.strength = ReadCoord();
177         self.falloff = ReadByte();
178         self.active = ReadByte();
179
180         trigger_common_read(true);
181
182
183         self.classname = "trigger_impulse";
184         self.solid = SOLID_TRIGGER;
185         self.entremove = trigger_remove_generic;
186         self.draw = trigger_draw_generic;
187         self.drawmask = MASK_NORMAL;
188         self.move_time = time;
189
190         if(self.radius) { self.trigger_touch = trigger_impulse_touch3; }
191         else if(self.target) { self.trigger_touch = trigger_impulse_touch1; }
192         else { self.trigger_touch = trigger_impulse_touch2; }
193 }
194 #endif