]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/platforms.qc
Merge branch 'TimePath/slist_refresh' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / platforms.qc
1 void generic_plat_blocked(entity this, entity blocker)
2 {
3 #ifdef SVQC
4         if(this.dmg && blocker.takedamage != DAMAGE_NO)
5         {
6                 if(this.dmgtime2 < time)
7                 {
8                         Damage (blocker, this, this, this.dmg, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
9                         this.dmgtime2 = time + this.dmgtime;
10                 }
11
12                 // Gib dead/dying stuff
13                 if(IS_DEAD(blocker))
14                         Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
15         }
16 #endif
17 }
18
19 void plat_spawn_inside_trigger(entity this)
20 {
21         entity trigger;
22         vector tmin, tmax;
23
24         trigger = spawn();
25         settouch(trigger, plat_center_touch);
26         set_movetype(trigger, MOVETYPE_NONE);
27         trigger.solid = SOLID_TRIGGER;
28         trigger.enemy = this;
29
30         tmin = this.absmin + '25 25 0';
31         tmax = this.absmax - '25 25 -8';
32         tmin_z = tmax_z - (this.pos1_z - this.pos2_z + 8);
33         if (this.spawnflags & PLAT_LOW_TRIGGER)
34                 tmax_z = tmin_z + 8;
35
36         if (this.size_x <= 50)
37         {
38                 tmin_x = (this.mins_x + this.maxs_x) / 2;
39                 tmax_x = tmin_x + 1;
40         }
41         if (this.size_y <= 50)
42         {
43                 tmin_y = (this.mins_y + this.maxs_y) / 2;
44                 tmax_y = tmin_y + 1;
45         }
46
47         if(tmin_x < tmax_x)
48                 if(tmin_y < tmax_y)
49                         if(tmin_z < tmax_z)
50                         {
51                                 setsize (trigger, tmin, tmax);
52                                 return;
53                         }
54
55         // otherwise, something is fishy...
56         delete(trigger);
57         objerror(this, "plat_spawn_inside_trigger: platform has odd size or lip, can't spawn");
58 }
59
60 void plat_hit_top(entity this)
61 {
62         _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
63         this.state = 1;
64
65         SUB_THINK(this, plat_go_down);
66         this.SUB_NEXTTHINK = this.SUB_LTIME + 3;
67 }
68
69 void plat_hit_bottom(entity this)
70 {
71         _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
72         this.state = 2;
73 }
74
75 void plat_go_down(entity this)
76 {
77         _sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
78         this.state = 3;
79         SUB_CalcMove (this, this.pos2, TSPEED_LINEAR, this.speed, plat_hit_bottom);
80 }
81
82 void plat_go_up(entity this)
83 {
84         _sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
85         this.state = 4;
86         SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, plat_hit_top);
87 }
88
89 void plat_center_touch(entity this, entity toucher)
90 {
91 #ifdef SVQC
92         if (!toucher.iscreature)
93                 return;
94
95         if (toucher.health <= 0)
96                 return;
97 #elif defined(CSQC)
98         if (!IS_PLAYER(toucher))
99                 return;
100         if(IS_DEAD(toucher))
101                 return;
102 #endif
103
104         if (this.enemy.state == 2) {
105                 plat_go_up(this.enemy);
106         } else if (this.enemy.state == 1)
107                 this.enemy.SUB_NEXTTHINK = this.enemy.SUB_LTIME + 1;
108 }
109
110 void plat_outside_touch(entity this, entity toucher)
111 {
112 #ifdef SVQC
113         if (!toucher.iscreature)
114                 return;
115
116         if (toucher.health <= 0)
117                 return;
118 #elif defined(CSQC)
119         if (!IS_PLAYER(toucher))
120                 return;
121 #endif
122
123         if (this.enemy.state == 1) {
124             entity e = this.enemy;
125                 plat_go_down(e);
126     }
127 }
128
129 void plat_trigger_use(entity this, entity actor, entity trigger)
130 {
131         if (getthink(this))
132                 return;         // already activated
133         plat_go_down(this);
134 }
135
136
137 void plat_crush(entity this, entity blocker)
138 {
139         if((this.spawnflags & 4) && (blocker.takedamage != DAMAGE_NO))
140         { // KIll Kill Kill!!
141 #ifdef SVQC
142                 Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
143 #endif
144         }
145         else
146         {
147 #ifdef SVQC
148                 if((this.dmg) && (blocker.takedamage != DAMAGE_NO))
149                 {   // Shall we bite?
150                         Damage (blocker, this, this, this.dmg, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
151                         // Gib dead/dying stuff
152                         if(IS_DEAD(blocker))
153                                 Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
154                 }
155 #endif
156
157                 if (this.state == 4)
158                         plat_go_down (this);
159                 else if (this.state == 3)
160                         plat_go_up (this);
161         // when in other states, then the plat_crush event came delayed after
162         // plat state already had changed
163         // this isn't a bug per se!
164         }
165 }
166
167 void plat_use(entity this, entity actor, entity trigger)
168 {
169         this.use = func_null;
170         if (this.state != 4)
171                 objerror (this, "plat_use: not in up state");
172         plat_go_down(this);
173 }
174
175 .string sound1, sound2;
176
177 void plat_reset(entity this)
178 {
179         IFTARGETED
180         {
181                 setorigin(this, this.pos1);
182                 this.state = 4;
183                 this.use = plat_use;
184         }
185         else
186         {
187                 setorigin(this, this.pos2);
188                 this.state = 2;
189                 this.use = plat_trigger_use;
190         }
191
192 #ifdef SVQC
193         this.SendFlags |= SF_TRIGGER_RESET;
194 #endif
195 }
196
197 .float platmovetype_start_default, platmovetype_end_default;
198 bool set_platmovetype(entity e, string s)
199 {
200         // sets platmovetype_start and platmovetype_end based on a string consisting of two values
201
202         int n = tokenize_console(s);
203         if(n > 0)
204                 e.platmovetype_start = stof(argv(0));
205         else
206                 e.platmovetype_start = 0;
207
208         if(n > 1)
209                 e.platmovetype_end = stof(argv(1));
210         else
211                 e.platmovetype_end = e.platmovetype_start;
212
213         if(n > 2)
214                 if(argv(2) == "force")
215                         return true; // no checking, return immediately
216
217         if(!cubic_speedfunc_is_sane(e.platmovetype_start, e.platmovetype_end))
218         {
219                 objerror(e, "Invalid platform move type; platform would go in reverse, which is not allowed.");
220                 return false;
221         }
222
223         return true;
224 }