]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/trigger/impulse.qc
More fun stuff
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / trigger / impulse.qc
1 #ifdef SVQC
2 // tZorks trigger impulse / gravity
3 .float radius;
4 .float falloff;
5 .float strength;
6 .float lastpushtime;
7
8 // targeted (directional) mode
9 void trigger_impulse_touch1()
10 {
11         entity targ;
12     float pushdeltatime;
13     float str;
14
15         if (self.active != ACTIVE_ACTIVE)
16                 return;
17
18         if (!isPushable(other))
19                 return;
20
21         EXACTTRIGGER_TOUCH;
22
23     targ = find(world, targetname, self.target);
24     if(!targ)
25     {
26         objerror("trigger_force without a (valid) .target!\n");
27         remove(self);
28         return;
29     }
30
31     str = min(self.radius, vlen(self.origin - other.origin));
32
33     if(self.falloff == 1)
34         str = (str / self.radius) * self.strength;
35     else if(self.falloff == 2)
36         str = (1 - (str / self.radius)) * self.strength;
37     else
38         str = self.strength;
39
40     pushdeltatime = time - other.lastpushtime;
41     if (pushdeltatime > 0.15) pushdeltatime = 0;
42     other.lastpushtime = time;
43     if(!pushdeltatime) return;
44
45     other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
46     other.flags &= ~FL_ONGROUND;
47     UpdateCSQCProjectile(other);
48 }
49
50 // Directionless (accelerator/decelerator) mode
51 void trigger_impulse_touch2()
52 {
53     float pushdeltatime;
54
55         if (self.active != ACTIVE_ACTIVE)
56                 return;
57
58         if (!isPushable(other))
59                 return;
60
61         EXACTTRIGGER_TOUCH;
62
63     pushdeltatime = time - other.lastpushtime;
64     if (pushdeltatime > 0.15) pushdeltatime = 0;
65     other.lastpushtime = time;
66     if(!pushdeltatime) return;
67
68     // div0: ticrate independent, 1 = identity (not 20)
69     other.velocity = other.velocity * pow(self.strength, pushdeltatime);
70     UpdateCSQCProjectile(other);
71 }
72
73 // Spherical (gravity/repulsor) mode
74 void trigger_impulse_touch3()
75 {
76     float pushdeltatime;
77     float str;
78
79         if (self.active != ACTIVE_ACTIVE)
80                 return;
81
82         if (!isPushable(other))
83                 return;
84
85         EXACTTRIGGER_TOUCH;
86
87     pushdeltatime = time - other.lastpushtime;
88     if (pushdeltatime > 0.15) pushdeltatime = 0;
89     other.lastpushtime = time;
90     if(!pushdeltatime) return;
91
92     setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
93
94         str = min(self.radius, vlen(self.origin - other.origin));
95
96     if(self.falloff == 1)
97         str = (1 - str / self.radius) * self.strength; // 1 in the inside
98     else if(self.falloff == 2)
99         str = (str / self.radius) * self.strength; // 0 in the inside
100     else
101         str = self.strength;
102
103     other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
104     UpdateCSQCProjectile(other);
105 }
106
107 /*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
108 -------- KEYS --------
109 target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
110          If not, this trigger acts like a damper/accelerator field.
111
112 strength : This is how mutch force to add in the direction of .target each second
113            when .target is set. If not, this is hoe mutch to slow down/accelerate
114            someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
115
116 radius   : If set, act as a spherical device rather then a liniar one.
117
118 falloff : 0 = none, 1 = liniar, 2 = inverted liniar
119
120 -------- NOTES --------
121 Use a brush textured with common/origin in the trigger entity to determine the origin of the force
122 in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
123 */
124
125 void spawnfunc_trigger_impulse()
126 {
127         self.active = ACTIVE_ACTIVE;
128
129         EXACTTRIGGER_INIT;
130     if(self.radius)
131     {
132         if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
133         setorigin(self, self.origin);
134         setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
135         self.touch = trigger_impulse_touch3;
136     }
137     else
138     {
139         if(self.target)
140         {
141             if(!self.strength) self.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
142             self.touch = trigger_impulse_touch1;
143         }
144         else
145         {
146             if(!self.strength) self.strength = 0.9;
147                         self.strength = pow(self.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
148             self.touch = trigger_impulse_touch2;
149         }
150     }
151 }
152 #endif