]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/triggers/platforms.qc
Merge branch 'master' into matthiaskrgr/domicons
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / platforms.qc
diff --git a/qcsrc/common/triggers/platforms.qc b/qcsrc/common/triggers/platforms.qc
new file mode 100644 (file)
index 0000000..c1f481f
--- /dev/null
@@ -0,0 +1,229 @@
+void generic_plat_blocked(entity this, entity blocker)
+{
+#ifdef SVQC
+       if(this.dmg && blocker.takedamage != DAMAGE_NO)
+       {
+               if(this.dmgtime2 < time)
+               {
+                       Damage (blocker, this, this, this.dmg, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
+                       this.dmgtime2 = time + this.dmgtime;
+               }
+
+               // Gib dead/dying stuff
+               if(IS_DEAD(blocker))
+                       Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
+       }
+#endif
+}
+
+void plat_spawn_inside_trigger(entity this)
+{
+       entity trigger;
+       vector tmin, tmax;
+
+       trigger = spawn();
+       settouch(trigger, plat_center_touch);
+       trigger.movetype = MOVETYPE_NONE;
+       trigger.solid = SOLID_TRIGGER;
+       trigger.enemy = this;
+
+       tmin = this.absmin + '25 25 0';
+       tmax = this.absmax - '25 25 -8';
+       tmin_z = tmax_z - (this.pos1_z - this.pos2_z + 8);
+       if (this.spawnflags & PLAT_LOW_TRIGGER)
+               tmax_z = tmin_z + 8;
+
+       if (this.size_x <= 50)
+       {
+               tmin_x = (this.mins_x + this.maxs_x) / 2;
+               tmax_x = tmin_x + 1;
+       }
+       if (this.size_y <= 50)
+       {
+               tmin_y = (this.mins_y + this.maxs_y) / 2;
+               tmax_y = tmin_y + 1;
+       }
+
+       if(tmin_x < tmax_x)
+               if(tmin_y < tmax_y)
+                       if(tmin_z < tmax_z)
+                       {
+                               setsize (trigger, tmin, tmax);
+                               return;
+                       }
+
+       // otherwise, something is fishy...
+       remove(trigger);
+       objerror(this, "plat_spawn_inside_trigger: platform has odd size or lip, can't spawn");
+}
+
+void plat_hit_top(entity this)
+{
+       _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
+       this.state = 1;
+
+       SUB_THINK(this, plat_go_down);
+       this.SUB_NEXTTHINK = this.SUB_LTIME + 3;
+}
+
+void plat_hit_bottom(entity this)
+{
+       _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
+       this.state = 2;
+}
+
+void plat_go_down(entity this)
+{
+       _sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
+       this.state = 3;
+       SUB_CalcMove (this, this.pos2, TSPEED_LINEAR, this.speed, plat_hit_bottom);
+}
+
+void plat_go_up(entity this)
+{
+       _sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
+       this.state = 4;
+       SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, plat_hit_top);
+}
+
+void plat_center_touch(entity this, entity toucher)
+{
+#ifdef SVQC
+       if (!toucher.iscreature)
+               return;
+
+       if (toucher.health <= 0)
+               return;
+#elif defined(CSQC)
+       if (!IS_PLAYER(toucher))
+               return;
+       if(IS_DEAD(toucher))
+               return;
+#endif
+
+       if (this.enemy.state == 2) {
+               plat_go_up(this.enemy);
+       } else if (this.enemy.state == 1)
+               this.enemy.SUB_NEXTTHINK = this.enemy.SUB_LTIME + 1;
+}
+
+void plat_outside_touch(entity this, entity toucher)
+{
+#ifdef SVQC
+       if (!toucher.iscreature)
+               return;
+
+       if (toucher.health <= 0)
+               return;
+#elif defined(CSQC)
+       if (!IS_PLAYER(toucher))
+               return;
+#endif
+
+       if (this.enemy.state == 1) {
+           entity e = this.enemy;
+               plat_go_down(e);
+    }
+}
+
+void plat_trigger_use(entity this, entity actor, entity trigger)
+{
+#ifdef SVQC
+       if (getthink(this))
+               return;         // already activated
+#elif defined(CSQC)
+       if(this.move_think)
+               return;
+#endif
+       plat_go_down(this);
+}
+
+
+void plat_crush(entity this, entity blocker)
+{
+       if((this.spawnflags & 4) && (blocker.takedamage != DAMAGE_NO))
+       { // KIll Kill Kill!!
+#ifdef SVQC
+               Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
+#endif
+       }
+       else
+       {
+#ifdef SVQC
+               if((this.dmg) && (blocker.takedamage != DAMAGE_NO))
+               {   // Shall we bite?
+                       Damage (blocker, this, this, this.dmg, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
+                       // Gib dead/dying stuff
+                       if(IS_DEAD(blocker))
+                               Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, blocker.origin, '0 0 0');
+               }
+#endif
+
+               if (this.state == 4)
+                       plat_go_down (this);
+               else if (this.state == 3)
+                       plat_go_up (this);
+       // when in other states, then the plat_crush event came delayed after
+       // plat state already had changed
+       // this isn't a bug per se!
+       }
+}
+
+void plat_use(entity this, entity actor, entity trigger)
+{
+       this.use = func_null;
+       if (this.state != 4)
+               objerror (this, "plat_use: not in up state");
+       plat_go_down(this);
+}
+
+.string sound1, sound2;
+
+void plat_reset(entity this)
+{
+       IFTARGETED
+       {
+               setorigin(this, this.pos1);
+               this.state = 4;
+               this.use = plat_use;
+       }
+       else
+       {
+               setorigin(this, this.pos2);
+               this.state = 2;
+               this.use = plat_trigger_use;
+       }
+
+#ifdef SVQC
+       this.SendFlags |= SF_TRIGGER_RESET;
+#endif
+}
+
+.float platmovetype_start_default, platmovetype_end_default;
+bool set_platmovetype(entity e, string s)
+{
+       // sets platmovetype_start and platmovetype_end based on a string consisting of two values
+
+       int n = tokenize_console(s);
+       if(n > 0)
+               e.platmovetype_start = stof(argv(0));
+       else
+               e.platmovetype_start = 0;
+
+       if(n > 1)
+               e.platmovetype_end = stof(argv(1));
+       else
+               e.platmovetype_end = e.platmovetype_start;
+
+       if(n > 2)
+               if(argv(2) == "force")
+                       return true; // no checking, return immediately
+
+       if(!cubic_speedfunc_is_sane(e.platmovetype_start, e.platmovetype_end))
+       {
+               objerror(e, "Invalid platform move type; platform would go in reverse, which is not allowed.");
+               return false;
+       }
+
+       return true;
+}