3 // button and multiple button
5 void button_wait(entity this);
6 void button_return(entity this);
8 // in case button is deactivated by a relay_deactivate while it pressed down
9 // set both fields to -1 in button_return!!
10 .float wait_remaining;
11 .float activation_time;
13 void button_setactive(entity this, int astate)
15 int oldstate = this.active;
16 if (astate == ACTIVE_TOGGLE)
18 if (this.active == ACTIVE_ACTIVE)
19 this.active = ACTIVE_NOT;
21 this.active = ACTIVE_ACTIVE;
26 if (this.active == ACTIVE_ACTIVE && oldstate == ACTIVE_NOT)
28 // button was deactivated while it was pressed
29 if (this.wait_remaining >= 0)
31 this.nextthink = this.wait_remaining + this.ltime;
32 setthink(this, button_return);
35 else if (this.active == ACTIVE_NOT && oldstate == ACTIVE_ACTIVE)
37 // check if button is in pressed state
38 if (this.activation_time >= 0)
40 this.wait_remaining = this.wait - (time - this.activation_time);
45 void button_wait(entity this)
47 this.state = STATE_TOP;
50 this.nextthink = this.ltime + this.wait;
51 setthink(this, button_return);
53 SUB_UseTargets(this, this.enemy, NULL);
54 this.frame = 1; // use alternate textures
57 void button_done(entity this)
59 this.state = STATE_BOTTOM;
62 void button_return(entity this)
64 if (this.active != ACTIVE_ACTIVE)
68 this.state = STATE_DOWN;
69 SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, button_done);
70 this.frame = 0; // use normal textures
71 if (GetResource(this, RES_HEALTH))
72 this.takedamage = DAMAGE_YES; // can be shot again
73 this.wait_remaining = -1;
74 this.activation_time = -1;
78 void button_blocked(entity this, entity blocker)
80 // do nothing, just don't come all the way back out
84 void button_fire(entity this)
86 SetResourceExplicit(this, RES_HEALTH, this.max_health);
87 this.takedamage = DAMAGE_NO; // will be reset upon return
89 if (this.state == STATE_UP || this.state == STATE_TOP)
92 this.activation_time = time;
95 _sound (this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
97 this.state = STATE_UP;
98 SUB_CalcMove (this, this.pos2, TSPEED_LINEAR, this.speed, button_wait);
101 void button_reset(entity this)
103 SetResourceExplicit(this, RES_HEALTH, this.max_health);
104 setorigin(this, this.pos1);
105 this.frame = 0; // use normal textures
106 this.state = STATE_BOTTOM;
107 this.velocity = '0 0 0';
108 this.wait_remaining = -1;
109 this.activation_time = -1;
110 this.active = ACTIVE_ACTIVE;
111 setthink(this, func_null);
113 if (GetResource(this, RES_HEALTH))
114 this.takedamage = DAMAGE_YES; // can be shot again
117 void button_use(entity this, entity actor, entity trigger)
119 if(this.active != ACTIVE_ACTIVE)
126 void button_touch(entity this, entity toucher)
128 if (this.active != ACTIVE_ACTIVE)
132 if (!toucher.iscreature)
134 if(toucher.velocity * this.movedir < 0)
136 this.enemy = toucher;
138 this.enemy = toucher.owner;
142 void button_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
144 if (this.active != ACTIVE_ACTIVE)
146 if(this.spawnflags & NOSPLASH)
147 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
149 if (this.spawnflags & BUTTON_DONTACCUMULATEDMG)
151 if (GetResource(this, RES_HEALTH) <= damage)
153 this.enemy = attacker;
159 TakeResource(this, RES_HEALTH, damage);
160 if (GetResource(this, RES_HEALTH) <= 0)
162 this.enemy = attacker;
169 /*QUAKED spawnfunc_func_button (0 .5 .8) ?
170 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.
172 "angle" determines the opening direction
173 "target" all entities with a matching targetname will be used
174 "speed" override the default 40 speed
175 "wait" override the default 1 second wait (-1 = never return)
176 "lip" override the default 4 pixel lip remaining at end of move
177 "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
178 "noise" sound that is played when the button is activated
180 spawnfunc(func_button)
184 if (!InitMovingBrushTrigger(this))
186 this.effects |= EF_LOWPRECISION;
188 setblocked(this, button_blocked);
189 this.use = button_use;
191 // if (this.health == 0) // all buttons are now shootable
193 if (GetResource(this, RES_HEALTH))
195 this.max_health = GetResource(this, RES_HEALTH);
196 this.event_damage = button_damage;
197 this.takedamage = DAMAGE_YES;
200 settouch(this, button_touch);
209 if(this.wait == -1 && autocvar_sv_q3defragcompat)
210 this.wait = 0.1; // compatibility for q3df: "instant" return
213 precache_sound(this.noise);
215 this.draggable = drag_undraggable;
217 this.setactive = button_setactive;
219 this.pos1 = this.origin;
220 this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
221 this.flags |= FL_NOTARGET;
223 this.reset = button_reset;