+#include "button.qh"
#ifdef SVQC
// button and multiple button
void button_wait(entity this);
void button_return(entity this);
+// in case button is deactivated by a relay_deactivate while it pressed down
+// set both fields to -1 in button_return!!
+.float wait_remaining;
+.float activation_time;
+
+void button_setactive(entity this, int astate)
+{
+ int oldstate = this.active;
+ if (astate == ACTIVE_TOGGLE)
+ {
+ if (this.active == ACTIVE_ACTIVE)
+ this.active = ACTIVE_NOT;
+ else
+ this.active = ACTIVE_ACTIVE;
+ }
+ else
+ this.active = astate;
+
+ if (this.active == ACTIVE_ACTIVE && oldstate == ACTIVE_NOT)
+ {
+ // button was deactivated while it was pressed
+ if (this.wait_remaining >= 0)
+ {
+ this.nextthink = this.wait_remaining + this.ltime;
+ setthink(this, button_return);
+ }
+ }
+ else if (this.active == ACTIVE_NOT && oldstate == ACTIVE_ACTIVE)
+ {
+ // check if button is in pressed state
+ if (this.activation_time >= 0)
+ {
+ this.wait_remaining = this.wait - (time - this.activation_time);
+ }
+ }
+}
+
void button_wait(entity this)
{
- self.state = STATE_TOP;
- self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
- SUB_THINK(self, button_return);
- SUB_UseTargets(self, self.enemy, NULL);
- self.frame = 1; // use alternate textures
+ this.state = STATE_TOP;
+ if(this.wait >= 0)
+ {
+ this.nextthink = this.ltime + this.wait;
+ setthink(this, button_return);
+ }
+ SUB_UseTargets(this, this.enemy, NULL);
+ this.frame = 1; // use alternate textures
}
void button_done(entity this)
{
- self.state = STATE_BOTTOM;
+ this.state = STATE_BOTTOM;
}
void button_return(entity this)
{
- self.state = STATE_DOWN;
- SUB_CalcMove (self, self.pos1, TSPEED_LINEAR, self.speed, button_done);
- self.frame = 0; // use normal textures
- if (self.health)
- self.takedamage = DAMAGE_YES; // can be shot again
+ if (this.active != ACTIVE_ACTIVE)
+ {
+ return;
+ }
+ this.state = STATE_DOWN;
+ SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, button_done);
+ this.frame = 0; // use normal textures
+ if (this.health)
+ this.takedamage = DAMAGE_YES; // can be shot again
+ this.wait_remaining = -1;
+ this.activation_time = -1;
}
-void button_blocked()
+void button_blocked(entity this, entity blocker)
{
// do nothing, just don't come all the way back out
}
void button_fire(entity this)
{
- self.health = self.max_health;
- self.takedamage = DAMAGE_NO; // will be reset upon return
+ this.health = this.max_health;
+ this.takedamage = DAMAGE_NO; // will be reset upon return
- if (self.state == STATE_UP || self.state == STATE_TOP)
+ if (this.state == STATE_UP || this.state == STATE_TOP)
return;
- if (self.noise != "")
- _sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ this.activation_time = time;
+
+ if (this.noise != "")
+ _sound (this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
- self.state = STATE_UP;
- SUB_CalcMove (self, self.pos2, TSPEED_LINEAR, self.speed, button_wait);
+ this.state = STATE_UP;
+ SUB_CalcMove (this, this.pos2, TSPEED_LINEAR, this.speed, button_wait);
}
void button_reset(entity this)
setorigin(this, this.pos1);
this.frame = 0; // use normal textures
this.state = STATE_BOTTOM;
+ this.velocity = '0 0 0';
+ setthink(this, func_null);
+ this.nextthink = 0;
if (this.health)
this.takedamage = DAMAGE_YES; // can be shot again
}
return;
this.enemy = actor;
- WITHSELF(this, button_fire(this));
+ button_fire(this);
}
-void button_touch(entity this)
+void button_touch(entity this, entity toucher)
{
- if (!other)
+ if (this.active != ACTIVE_ACTIVE)
return;
- if (!other.iscreature)
+ if (!toucher)
return;
- if(other.velocity * self.movedir < 0)
+ if (!toucher.iscreature)
return;
- self.enemy = other;
- if (other.owner)
- self.enemy = other.owner;
- button_fire (self);
+ if(toucher.velocity * this.movedir < 0)
+ return;
+ this.enemy = toucher;
+ if (toucher.owner)
+ this.enemy = toucher.owner;
+ button_fire (this);
}
void button_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
{
+ if (this.active != ACTIVE_ACTIVE)
+ return;
if(this.spawnflags & DOOR_NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
this.health = this.health - damage;
if (this.health <= 0)
{
- this.enemy = damage_attacker;
- WITHSELF(this, button_fire(this));
+ this.enemy = attacker;
+ button_fire(this);
}
}
return;
this.effects |= EF_LOWPRECISION;
- this.blocked = button_blocked;
+ setblocked(this, button_blocked);
this.use = button_use;
// if (this.health == 0) // all buttons are now shootable
if (!this.lip)
this.lip = 4;
+ this.wait_remaining = -1;
+ this.activation_time = -1;
+
if(this.noise != "")
precache_sound(this.noise);
this.active = ACTIVE_ACTIVE;
+ this.setactive = button_setactive;
+
this.pos1 = this.origin;
this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
this.flags |= FL_NOTARGET;
+ this.reset = button_reset;
+
button_reset(this);
}
#endif