]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/func/button.qc
e6394d08543c979031d949a20eba624661a5ef3a
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / func / button.qc
1 #include "button.qh"
2 #ifdef SVQC
3 // button and multiple button
4
5 void button_wait(entity this);
6 void button_return(entity this);
7
8 .float wait_remaining;
9 .float activation_time;
10
11 void button_setactive(entity this, int astate)
12 {
13         int oldstate = this.active;
14         if (astate == ACTIVE_TOGGLE)
15         {
16                 if (this.active == ACTIVE_ACTIVE)
17                         this.active = ACTIVE_NOT;
18                 else
19                         this.active = ACTIVE_ACTIVE;
20         }
21         else
22                 this.active = astate;
23
24         if (this.active == ACTIVE_ACTIVE && oldstate == ACTIVE_NOT)
25         {
26                 if (this.wait_remaining >= 0)
27                 {
28                         this.nextthink =  this.wait_remaining + this.ltime;
29                         setthink(this, button_return);
30                 }
31         }
32         else if (this.active == ACTIVE_NOT && oldstate == ACTIVE_ACTIVE)
33         {
34                 this.wait_remaining = this.wait - (time - this.activation_time);
35         }
36 }
37
38 void button_wait(entity this)
39 {
40         this.state = STATE_TOP;
41         if(this.wait >= 0)
42         {
43                 this.nextthink = this.ltime + this.wait;
44                 setthink(this, button_return);
45         }
46         SUB_UseTargets(this, this.enemy, NULL);
47         this.frame = 1;                 // use alternate textures
48 }
49
50 void button_done(entity this)
51 {
52         this.state = STATE_BOTTOM;
53 }
54
55 void button_return(entity this)
56 {
57         if (this.active != ACTIVE_ACTIVE)
58         {
59                 return;
60         }
61         this.state = STATE_DOWN;
62         SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, button_done);
63         this.frame = 0;                 // use normal textures
64         if (this.health)
65                 this.takedamage = DAMAGE_YES;   // can be shot again
66         this.wait_remaining = this.wait;
67 }
68
69
70 void button_blocked(entity this, entity blocker)
71 {
72         // do nothing, just don't come all the way back out
73 }
74
75
76 void button_fire(entity this)
77 {
78         this.health = this.max_health;
79         this.takedamage = DAMAGE_NO;    // will be reset upon return
80
81         if (this.state == STATE_UP || this.state == STATE_TOP)
82                 return;
83
84         this.activation_time = time;
85
86         if (this.noise != "")
87                 _sound (this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
88
89         this.state = STATE_UP;
90         SUB_CalcMove (this, this.pos2, TSPEED_LINEAR, this.speed, button_wait);
91 }
92
93 void button_reset(entity this)
94 {
95         this.health = this.max_health;
96         setorigin(this, this.pos1);
97         this.frame = 0;                 // use normal textures
98         this.state = STATE_BOTTOM;
99         this.velocity = '0 0 0';
100         setthink(this, func_null);
101         this.nextthink = 0;
102         if (this.health)
103                 this.takedamage = DAMAGE_YES;   // can be shot again
104 }
105
106 void button_use(entity this, entity actor, entity trigger)
107 {
108         if(this.active != ACTIVE_ACTIVE)
109                 return;
110
111         this.enemy = actor;
112         button_fire(this);
113 }
114
115 void button_touch(entity this, entity toucher)
116 {
117         if (this.active != ACTIVE_ACTIVE)
118                 return;
119         if (!toucher)
120                 return;
121         if (!toucher.iscreature)
122                 return;
123         if(toucher.velocity * this.movedir < 0)
124                 return;
125         this.enemy = toucher;
126         if (toucher.owner)
127                 this.enemy = toucher.owner;
128         button_fire (this);
129 }
130
131 void button_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
132 {
133         if (this.active != ACTIVE_ACTIVE)
134                 return;
135         if(this.spawnflags & DOOR_NOSPLASH)
136                 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
137                         return;
138         this.health = this.health - damage;
139         if (this.health <= 0)
140         {
141                 this.enemy = attacker;
142                 button_fire(this);
143         }
144 }
145
146
147 /*QUAKED spawnfunc_func_button (0 .5 .8) ?
148 When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
149
150 "angle"         determines the opening direction
151 "target"        all entities with a matching targetname will be used
152 "speed"         override the default 40 speed
153 "wait"          override the default 1 second wait (-1 = never return)
154 "lip"           override the default 4 pixel lip remaining at end of move
155 "health"        if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the InstaGib laser
156 "sounds"
157 0) steam metal
158 1) wooden clunk
159 2) metallic click
160 3) in-out
161 */
162 spawnfunc(func_button)
163 {
164         SetMovedir(this);
165
166         if (!InitMovingBrushTrigger(this))
167                 return;
168         this.effects |= EF_LOWPRECISION;
169
170         setblocked(this, button_blocked);
171         this.use = button_use;
172
173 //      if (this.health == 0) // all buttons are now shootable
174 //              this.health = 10;
175         if (this.health)
176         {
177                 this.max_health = this.health;
178                 this.event_damage = button_damage;
179                 this.takedamage = DAMAGE_YES;
180         }
181         else
182                 settouch(this, button_touch);
183
184         if (!this.speed)
185                 this.speed = 40;
186         if (!this.wait)
187                 this.wait = 1;
188         if (!this.lip)
189                 this.lip = 4;
190
191         this.wait_remaining = this.wait;
192
193     if(this.noise != "")
194         precache_sound(this.noise);
195
196         this.active = ACTIVE_ACTIVE;
197
198         this.setactive = button_setactive;
199
200         this.pos1 = this.origin;
201         this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
202     this.flags |= FL_NOTARGET;
203
204     this.reset = button_reset;
205
206         button_reset(this);
207 }
208 #endif