]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/platforms.qc
A few trillion lines of untested junk, committing now so it doesn't become quadrillions
[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         trigger_setnextthink(self, 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         self = self.enemy;
147         if (self.state == 2)
148                 plat_go_up ();
149         else if (self.state == 1)
150                 trigger_setnextthink(self, self.ltime + 1);
151 }
152
153 void plat_outside_touch()
154 {
155 #ifdef SVQC
156         if (!other.iscreature)
157                 return;
158
159         if (other.health <= 0)
160                 return;
161 #elif defined(CSQC)
162         if (!IS_PLAYER(other))
163                 return;
164 #endif
165
166         self = self.enemy;
167         if (self.state == 1)
168                 plat_go_down ();
169 }
170
171 void plat_trigger_use()
172 {
173         if (self.think)
174                 return;         // already activated
175         plat_go_down();
176 }
177
178
179 void plat_crush()
180 {
181         if((self.spawnflags & 4) && (other.takedamage != DAMAGE_NO))
182         { // KIll Kill Kill!!
183 #ifdef SVQC
184                 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
185 #endif
186         }
187         else
188         {
189 #ifdef SVQC
190                 if((self.dmg) && (other.takedamage != DAMAGE_NO))
191                 {   // Shall we bite?
192                         Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
193                         // Gib dead/dying stuff
194                         if(other.deadflag != DEAD_NO)
195                                 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
196                 }
197 #endif
198
199                 if (self.state == 4)
200                         plat_go_down ();
201                 else if (self.state == 3)
202                         plat_go_up ();
203         // when in other states, then the plat_crush event came delayed after
204         // plat state already had changed
205         // this isn't a bug per se!
206         }
207 }
208
209 void plat_use()
210 {
211         self.use = func_null;
212         if (self.state != 4)
213                 objerror ("plat_use: not in up state");
214         plat_go_down();
215 }
216
217 .string sound1, sound2;
218
219 void plat_reset()
220 {
221         IFTARGETED
222         {
223                 setorigin (self, self.pos1);
224                 self.state = 4;
225                 self.use = plat_use;
226         }
227         else
228         {
229                 setorigin (self, self.pos2);
230                 self.state = 2;
231                 self.use = plat_trigger_use;
232         }
233
234 #ifdef SVQC
235         self.SendFlags |= SF_TRIGGER_RESET;
236 #endif
237 }
238
239 .float platmovetype_start_default, platmovetype_end_default;
240 bool set_platmovetype(entity e, string s)
241 {
242         // sets platmovetype_start and platmovetype_end based on a string consisting of two values
243
244         int n = tokenize_console(s);
245         if(n > 0)
246                 e.platmovetype_start = stof(argv(0));
247         else
248                 e.platmovetype_start = 0;
249
250         if(n > 1)
251                 e.platmovetype_end = stof(argv(1));
252         else
253                 e.platmovetype_end = e.platmovetype_start;
254
255         if(n > 2)
256                 if(argv(2) == "force")
257                         return true; // no checking, return immediately
258
259         if(!cubic_speedfunc_is_sane(e.platmovetype_start, e.platmovetype_end))
260         {
261                 objerror("Invalid platform move type; platform would go in reverse, which is not allowed.");
262                 return false;
263         }
264
265         return true;
266 }