]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/platforms.qc
Merge branch 'TimePath/experiments/csqc_prediction' into Mario/qc_physics
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / platforms.qc
1 void generic_plat_blocked()
2 {
3 #ifdef SVQC
4         if(self.dmg && other.takedamage != DAMAGE_NO)
5         {
6                 if(self.dmgtime2 < time)
7                 {
8                         Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
9                         self.dmgtime2 = time + self.dmgtime;
10                 }
11
12                 // Gib dead/dying stuff
13                 if(other.deadflag != DEAD_NO)
14                         Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
15         }
16 #endif
17 }
18
19 #ifdef SVQC
20 float plat_trigger_send(entity to, float sf)
21 {
22         WriteByte(MSG_ENTITY, ENT_CLIENT_PLAT_TRIGGER);
23         WriteShort(MSG_ENTITY, num_for_edict(self.enemy));
24
25         WriteCoord(MSG_ENTITY, self.origin_x);
26         WriteCoord(MSG_ENTITY, self.origin_y);
27         WriteCoord(MSG_ENTITY, self.origin_z);
28
29         WriteCoord(MSG_ENTITY, self.mins_x);
30         WriteCoord(MSG_ENTITY, self.mins_y);
31         WriteCoord(MSG_ENTITY, self.mins_z);
32         WriteCoord(MSG_ENTITY, self.maxs_x);
33         WriteCoord(MSG_ENTITY, self.maxs_y);
34         WriteCoord(MSG_ENTITY, self.maxs_z);
35         return true;
36 }
37
38 void plat_spawn_inside_trigger()
39 {
40         entity trigger;
41         vector tmin, tmax;
42
43         trigger = spawn();
44         trigger.touch = plat_center_touch;
45         trigger.movetype = MOVETYPE_NONE;
46         trigger.solid = SOLID_TRIGGER;
47         trigger.enemy = self;
48
49         tmin = self.absmin + '25 25 0';
50         tmax = self.absmax - '25 25 -8';
51         tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
52         if (self.spawnflags & PLAT_LOW_TRIGGER)
53                 tmax_z = tmin_z + 8;
54
55         if (self.size_x <= 50)
56         {
57                 tmin_x = (self.mins_x + self.maxs_x) / 2;
58                 tmax_x = tmin_x + 1;
59         }
60         if (self.size_y <= 50)
61         {
62                 tmin_y = (self.mins_y + self.maxs_y) / 2;
63                 tmax_y = tmin_y + 1;
64         }
65
66         if(tmin_x < tmax_x)
67                 if(tmin_y < tmax_y)
68                         if(tmin_z < tmax_z)
69                         {
70                                 setsize (trigger, tmin, tmax);
71                                 Net_LinkEntity(trigger, false, 0, plat_trigger_send);
72                                 return;
73                         }
74
75         // otherwise, something is fishy...
76         remove(trigger);
77         objerror("plat_spawn_inside_trigger: platform has odd size or lip, can't spawn");
78 }
79 #elif defined(CSQC)
80 void ent_plat_trigger()
81 {
82         float myenemy = ReadShort();
83         self.origin_x = ReadCoord();
84         self.origin_y = ReadCoord();
85         self.origin_z = ReadCoord();
86         setorigin(self, self.origin);
87
88         self.mins_x = ReadCoord();
89         self.mins_y = ReadCoord();
90         self.mins_z = ReadCoord();
91         self.maxs_x = ReadCoord();
92         self.maxs_y = ReadCoord();
93         self.maxs_z = ReadCoord();
94         setsize(self, self.mins, self.maxs);
95
96         self.enemy = findfloat(world, sv_entnum, myenemy);
97         if(!self.enemy) { print("^1BAD BAD BAD!!!\n"); }
98         self.drawmask = MASK_NORMAL;
99         self.draw = trigger_draw_generic;
100         self.trigger_touch = plat_center_touch;
101         self.solid = SOLID_TRIGGER;
102 }
103 #endif
104
105 void plat_hit_top()
106 {
107         sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
108         self.state = 1;
109         self.think = plat_go_down;
110         self.nextthink = self.ltime + 3;
111 }
112
113 void plat_hit_bottom()
114 {
115         sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
116         self.state = 2;
117 }
118
119 void plat_go_down()
120 {
121         sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
122         self.state = 3;
123         SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, plat_hit_bottom);
124 }
125
126 void plat_go_up()
127 {
128         sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
129         self.state = 4;
130         SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, plat_hit_top);
131 }
132
133 void plat_center_touch()
134 {
135 #ifdef SVQC
136         if (!other.iscreature)
137                 return;
138
139         if (other.health <= 0)
140                 return;
141 #elif defined(CSQC)
142         if (!IS_PLAYER(other))
143                 return;
144 #endif
145
146 #ifdef CSQC
147         print("Got this far\n");
148 #endif
149
150         self = self.enemy;
151         if (self.state == 2)
152                 plat_go_up ();
153         else if (self.state == 1)
154                 self.nextthink = self.ltime + 1;        // delay going down
155 }
156
157 void plat_outside_touch()
158 {
159 #ifdef SVQC
160         if (!other.iscreature)
161                 return;
162
163         if (other.health <= 0)
164                 return;
165 #elif defined(CSQC)
166         if (!IS_PLAYER(other))
167                 return;
168 #endif
169
170         self = self.enemy;
171         if (self.state == 1)
172                 plat_go_down ();
173 }
174
175 void plat_trigger_use()
176 {
177         if (self.think)
178                 return;         // already activated
179         plat_go_down();
180 }
181
182
183 void plat_crush()
184 {
185         if((self.spawnflags & 4) && (other.takedamage != DAMAGE_NO))
186         { // KIll Kill Kill!!
187 #ifdef SVQC
188                 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
189 #endif
190         }
191         else
192         {
193 #ifdef SVQC
194                 if((self.dmg) && (other.takedamage != DAMAGE_NO))
195                 {   // Shall we bite?
196                         Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
197                         // Gib dead/dying stuff
198                         if(other.deadflag != DEAD_NO)
199                                 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
200                 }
201 #endif
202
203                 if (self.state == 4)
204                         plat_go_down ();
205                 else if (self.state == 3)
206                         plat_go_up ();
207         // when in other states, then the plat_crush event came delayed after
208         // plat state already had changed
209         // this isn't a bug per se!
210         }
211 }
212
213 void plat_use()
214 {
215         self.use = func_null;
216         if (self.state != 4)
217                 objerror ("plat_use: not in up state");
218         plat_go_down();
219 }
220
221 .string sound1, sound2;
222
223 void plat_reset()
224 {
225         IFTARGETED
226         {
227                 setorigin (self, self.pos1);
228                 self.state = 4;
229                 self.use = plat_use;
230         }
231         else
232         {
233                 setorigin (self, self.pos2);
234                 self.state = 2;
235                 self.use = plat_trigger_use;
236         }
237
238 #ifdef SVQC
239         self.SendFlags |= SF_TRIGGER_RESET;
240 #endif
241 }
242
243 #ifdef SVQC
244 .float platmovetype_start_default, platmovetype_end_default;
245 float set_platmovetype(entity e, string s)
246 {
247         // sets platmovetype_start and platmovetype_end based on a string consisting of two values
248
249         float n;
250         n = tokenize_console(s);
251         if(n > 0)
252                 e.platmovetype_start = stof(argv(0));
253         else
254                 e.platmovetype_start = 0;
255
256         if(n > 1)
257                 e.platmovetype_end = stof(argv(1));
258         else
259                 e.platmovetype_end = e.platmovetype_start;
260
261         if(n > 2)
262                 if(argv(2) == "force")
263                         return true; // no checking, return immediately
264
265         if(!cubic_speedfunc_is_sane(e.platmovetype_start, e.platmovetype_end))
266         {
267                 objerror("Invalid platform move type; platform would go in reverse, which is not allowed.");
268                 return false;
269         }
270
271         return true;
272 }
273 #endif