]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/func/door_rotating.qc
f52b221ba0127c28a6eda5ff9b0b079c7c5578f7
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / func / door_rotating.qc
1 #include "door_rotating.qh"
2 /*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS
3 if two doors touch, they are assumed to be connected and operate as a unit.
4
5 TOGGLE causes the door to wait in both the start and end states for a trigger event.
6
7 BIDIR makes the door work bidirectional, so that the opening direction is always away from the requestor.
8 The usage of bidirectional doors requires two manually instantiated triggers (trigger_multiple), the one to open it in the other direction
9 must have set trigger_reverse to 1.
10 BIDIR_IN_DOWN will the door prevent from reopening while closing if it is triggered from the other side.
11
12 START_OPEN causes the door to move to its destination when spawned, and operate in reverse.  It is used to temporarily or permanently close off an area when triggered (not usefull for touch or takedamage doors).
13
14 "message"       is printed when the door is touched if it is a trigger door and it hasn't been fired yet
15 "angle"         determines the destination angle for opening. negative values reverse the direction.
16 "targetname"    if set, no touch field will be spawned and a remote button or trigger field activates the door.
17 "health"        if set, door must be shot open
18 "speed"         movement speed (100 default)
19 "wait"          wait before returning (3 default, -1 = never return)
20 "dmg"           damage to inflict when blocked (2 default)
21 "sounds"
22 0)      no sound
23 1)      stone
24 2)      base
25 3)      stone chain
26 4)      screechy metal
27 FIXME: only one sound set available at the time being
28 */
29
30 #ifdef GAMEQC
31 void door_rotating_hit_top(entity this)
32 {
33         if (this.noise1 != "")
34                 _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
35         this.state = STATE_TOP;
36         if (this.spawnflags & DOOR_TOGGLE)
37                 return;         // don't come down automatically
38         setthink(this, door_rotating_go_down);
39         this.nextthink = this.ltime + this.wait;
40 }
41
42 void door_rotating_hit_bottom(entity this)
43 {
44         if (this.noise1 != "")
45                 _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
46         if (this.lip==666) // this.lip is used to remember reverse opening direction for door_rotating
47         {
48                 this.pos2 = '0 0 0' - this.pos2;
49                 this.lip = 0;
50         }
51         this.state = STATE_BOTTOM;
52 }
53
54 void door_rotating_go_down(entity this)
55 {
56         if (this.noise2 != "")
57                 _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
58         if (this.max_health)
59         {
60                 this.takedamage = DAMAGE_YES;
61                 this.health = this.max_health;
62         }
63
64         this.state = STATE_DOWN;
65         SUB_CalcAngleMove (this, this.pos1, TSPEED_LINEAR, this.speed, door_rotating_hit_bottom);
66 }
67
68 void door_rotating_go_up(entity this, entity oth)
69 {
70         if (this.state == STATE_UP)
71                 return;         // already going up
72
73         if (this.state == STATE_TOP)
74         {       // reset top wait time
75                 this.nextthink = this.ltime + this.wait;
76                 return;
77         }
78         if (this.noise2 != "")
79                 _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
80         this.state = STATE_UP;
81         SUB_CalcAngleMove (this, this.pos2, TSPEED_LINEAR, this.speed, door_rotating_hit_top);
82
83         string oldmessage;
84         oldmessage = this.message;
85         this.message = "";
86         SUB_UseTargets(this, NULL, oth); // TODO: is oth needed here?
87         this.message = oldmessage;
88 }
89 #endif
90
91 #ifdef SVQC
92 void door_rotating_reset(entity this)
93 {
94         this.angles = this.pos1;
95         this.avelocity = '0 0 0';
96         this.state = STATE_BOTTOM;
97         setthink(this, func_null);
98         this.nextthink = 0;
99 }
100
101 void door_rotating_init_startopen(entity this)
102 {
103         this.angles = this.movedir;
104         this.pos2 = '0 0 0';
105         this.pos1 = this.movedir;
106 }
107
108 spawnfunc(func_door_rotating)
109 {
110         // possible TODO: support for Quake1 keys (like func_door)
111         // however SPAWNFLAGS_GOLD_KEY (==8) has the same value as BIDIR_IN_DOWN
112
113         //if (!this.deathtype) // map makers can override this
114         //      this.deathtype = " got in the way";
115
116         // I abuse "movedir" for denoting the axis for now
117         if (this.spawnflags & DOOR_ROTATING_XAXIS)
118                 this.movedir = '0 0 1';
119         else if (this.spawnflags & DOOR_ROTATING_YAXIS)
120                 this.movedir = '1 0 0';
121         else // Z
122                 this.movedir = '0 1 0';
123
124         if (this.angles_y==0) this.angles_y = 90;
125
126         this.movedir = this.movedir * this.angles_y;
127         this.angles = '0 0 0';
128
129         this.max_health = this.health;
130         this.avelocity = this.movedir;
131         if (!InitMovingBrushTrigger(this))
132                 return;
133         this.velocity = '0 0 0';
134         //this.effects |= EF_LOWPRECISION;
135         this.classname = "door_rotating";
136
137         setblocked(this, door_blocked);
138         this.use = door_use;
139
140     if(this.dmg && (this.message == ""))
141                 this.message = "was squished";
142     if(this.dmg && (this.message2 == ""))
143                 this.message2 = "was squished by";
144
145         if (this.sounds > 0)
146         {
147                 this.noise2 = "plats/medplat1.wav";
148                 this.noise1 = "plats/medplat2.wav";
149         }
150         if(this.noise1 && this.noise1 != "")
151         {
152                 precache_sound(this.noise1);
153         }
154         if(this.noise2 && this.noise2 != "")
155         {
156                 precache_sound(this.noise2);
157         }
158
159         if (!this.speed)
160                 this.speed = 50;
161         if (!this.wait)
162                 this.wait = 1;
163         this.lip = 0; // this.lip is used to remember reverse opening direction for door_rotating
164
165         this.pos1 = '0 0 0';
166         this.pos2 = this.movedir;
167
168 // DOOR_START_OPEN is to allow an entity to be lighted in the closed position
169 // but spawn in the open position
170         if (this.spawnflags & DOOR_START_OPEN)
171                 InitializeEntity(this, door_rotating_init_startopen, INITPRIO_SETLOCATION);
172
173         this.state = STATE_BOTTOM;
174
175         if (this.health)
176         {
177                 //this.canteamdamage = true; // TODO
178                 this.takedamage = DAMAGE_YES;
179                 this.event_damage = door_damage;
180         }
181
182         if (this.items)
183                 this.wait = -1;
184
185         settouch(this, door_touch);
186
187 // LinkDoors can't be done until all of the doors have been spawned, so
188 // the sizes can be detected properly.
189         InitializeEntity(this, LinkDoors, INITPRIO_LINKDOORS);
190
191         this.reset = door_rotating_reset;
192 }
193 #endif