]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_triggers.qc
Merge branch 'master' into terencehill/centerprint_stuff
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_triggers.qc
index 4a66f229380ea9c505962ae4e5aa0abe9674d171..6407cefaa901351ada791a7e5e2dffb084d0fb18 100644 (file)
@@ -51,6 +51,9 @@ void SUB_UseTargets()
                t.message = self.message;
                t.killtarget = self.killtarget;
                t.target = self.target;
+               t.target2 = self.target2;
+               t.target3 = self.target3;
+               t.target4 = self.target4;
                return;
        }
 
@@ -85,6 +88,9 @@ void SUB_UseTargets()
        stemp = self;
        otemp = other;
 
+       if(stemp.target_random)
+               RandomSelection_Init();
+
        for(i = 0; i < 4; ++i)
        {
                switch(i)
@@ -100,15 +106,29 @@ void SUB_UseTargets()
                        for(t = world; (t = find(t, targetname, s)); )
                        if(t.use)
                        {
-                               //print(stemp.classname, " ", stemp.targetname, " -> ", t.classname, " ", t.targetname, "\n");
-                               self = t;
-                               other = stemp;
-                               activator = act;
-                               self.use();
+                               if(stemp.target_random)
+                               {
+                                       RandomSelection_Add(t, 0, string_null, 1, 0);
+                               }
+                               else
+                               {
+                                       self = t;
+                                       other = stemp;
+                                       activator = act;
+                                       self.use();
+                               }
                        }
                }
        }
 
+       if(stemp.target_random && RandomSelection_chosen_ent)
+       {
+               self = RandomSelection_chosen_ent;
+               other = stemp;
+               activator = act;
+               self.use();
+       }
+
        activator = act;
        self = stemp;
        other = otemp;
@@ -151,7 +171,7 @@ void multi_trigger()
        }
 
        if (self.noise)
-               sound (self.enemy, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM);
+               sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
 
 // don't trigger again until reset
        self.takedamage = DAMAGE_NO;
@@ -186,14 +206,12 @@ void multi_use()
 void multi_touch()
 {
        if not(self.spawnflags & 2)
-       {
                if not(other.iscreature)
                        return;
 
-               if(self.team)
-               if(self.team == other.team)
+       if(self.team)
+               if((self.spawnflags & 4 == 0) == (self.team != other.team))
                        return;
-       }
 
 // if the trigger has an angles field, check player's facing direction
        if (self.movedir != '0 0 0')
@@ -410,6 +428,14 @@ void spawnfunc_trigger_counter()
        self.reset = counter_reset;
 };
 
+void trigger_hurt_use()
+{
+       if(activator.classname == "player")
+               self.enemy = activator;
+       else
+               self.enemy = world; // let's just destroy it, if taking over is too much work
+}
+
 .float triggerhurttime;
 void trigger_hurt_touch()
 {
@@ -428,7 +454,16 @@ void trigger_hurt_touch()
                {
                        EXACTTRIGGER_TOUCH;
                        other.triggerhurttime = time + 1;
-                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+
+                       entity own;
+                       own = self.enemy;
+                       if(own.classname != "player")
+                       {
+                               own = self;
+                               self.enemy = world; // I still hate you all
+                       }
+
+                       Damage (other, self, own, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
                }
        }
        else
@@ -464,6 +499,8 @@ void spawnfunc_trigger_hurt()
        EXACTTRIGGER_INIT;
        self.active = ACTIVE_ACTIVE;
        self.touch = trigger_hurt_touch;
+       self.use = trigger_hurt_use;
+       self.enemy = world; // I hate you all
        if (!self.dmg)
                self.dmg = 1000;
        if (!self.message)
@@ -516,8 +553,8 @@ void trigger_heal_touch()
                        if (other.health < self.max_health)
                        {
                                other.health = min(other.health + self.health, self.max_health);
-                               other.pauserothealth_finished = max(other.pauserothealth_finished, time + cvar("g_balance_pause_health_rot"));
-                               sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM);
+                               other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
+                               sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
                        }
                }
        }
@@ -628,7 +665,7 @@ void trigger_gravity_touch()
        {
                other.gravity = g;
                if(self.noise != "")
-                       sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM);
+                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
                UpdateCSQCProjectile(self.owner);
        }
 };
@@ -656,31 +693,134 @@ void spawnfunc_trigger_gravity()
 
 // TODO add a way to do looped sounds with sound(); then complete this entity
 .float volume, atten;
-void target_speaker_use() {sound(self, CHAN_TRIGGER, self.noise, VOL_BASE * self.volume, self.atten);}
+void target_speaker_use_off();
+void target_speaker_use_activator()
+{
+       if(clienttype(activator) != CLIENTTYPE_REAL)
+               return;
+       string snd;
+       if(substring(self.noise, 0, 1) == "*")
+       {
+               var .string sample;
+               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+               if(GetPlayerSoundSampleField_notFound)
+                       snd = "misc/null.wav";
+               else if(activator.sample == "")
+                       snd = "misc/null.wav";
+               else
+               {
+                       tokenize_console(activator.sample);
+                       float n;
+                       n = stof(argv(1));
+                       if(n > 0)
+                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
+                       else
+                               snd = strcat(argv(0), ".wav"); // randomization
+               }
+       }
+       else
+               snd = self.noise;
+       msg_entity = activator;
+       soundto(MSG_ONE, self, CH_TRIGGER, snd, VOL_BASE * self.volume, self.atten);
+}
+void target_speaker_use_on()
+{
+       string snd;
+       if(substring(self.noise, 0, 1) == "*")
+       {
+               var .string sample;
+               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+               if(GetPlayerSoundSampleField_notFound)
+                       snd = "misc/null.wav";
+               else if(activator.sample == "")
+                       snd = "misc/null.wav";
+               else
+               {
+                       tokenize_console(activator.sample);
+                       float n;
+                       n = stof(argv(1));
+                       if(n > 0)
+                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
+                       else
+                               snd = strcat(argv(0), ".wav"); // randomization
+               }
+       }
+       else
+               snd = self.noise;
+       sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
+       if(self.spawnflags & 3)
+               self.use = target_speaker_use_off;
+}
+void target_speaker_use_off()
+{
+       sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASE * self.volume, self.atten);
+       self.use = target_speaker_use_on;
+}
+void target_speaker_reset()
+{
+       if(self.spawnflags & 1) // LOOPED_ON
+       {
+               if(self.use == target_speaker_use_on)
+                       target_speaker_use_on();
+       }
+       else if(self.spawnflags & 2)
+       {
+               if(self.use == target_speaker_use_off)
+                       target_speaker_use_off();
+       }
+}
 
 void spawnfunc_target_speaker()
 {
+       // TODO: "*" prefix to sound file name
+       // TODO: wait and random (just, HOW? random is not a field)
        if(self.noise)
                precache_sound (self.noise);
-       IFTARGETED
+
+       if(!self.atten && !(self.spawnflags & 4))
        {
-               if(!self.atten)
+               IFTARGETED
                        self.atten = ATTN_NORM;
-               else if(self.atten < 0)
-                       self.atten = 0;
-               if(!self.volume)
-                       self.volume = 1;
-               self.use = target_speaker_use;
+               else
+                       self.atten = ATTN_STATIC;
+       }
+       else if(self.atten < 0)
+               self.atten = 0;
+
+       if(!self.volume)
+               self.volume = 1;
+
+       IFTARGETED
+       {
+               if(self.spawnflags & 8) // ACTIVATOR
+                       self.use = target_speaker_use_activator;
+               else if(self.spawnflags & 1) // LOOPED_ON
+               {
+                       target_speaker_use_on();
+                       self.reset = target_speaker_reset;
+               }
+               else if(self.spawnflags & 2) // LOOPED_OFF
+               {
+                       self.use = target_speaker_use_on;
+                       self.reset = target_speaker_reset;
+               }
+               else
+                       self.use = target_speaker_use_on;
+       }
+       else if(self.spawnflags & 1) // LOOPED_ON
+       {
+               ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
+               remove(self);
+       }
+       else if(self.spawnflags & 2) // LOOPED_OFF
+       {
+               objerror("This sound entity can never be activated");
        }
        else
        {
-               if(!self.atten)
-                       self.atten = ATTN_STATIC;
-               else if(self.atten < 0)
-                       self.atten = 0;
-               if(!self.volume)
-                       self.volume = 1;
+               // Quake/Nexuiz fallback
                ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
+               remove(self);
        }
 };
 
@@ -1237,24 +1377,7 @@ void trigger_impulse_touch1()
        if (self.active != ACTIVE_ACTIVE) 
                return;
 
-       // FIXME: Better checking for what to push and not.
-       if not(other.iscreature)
-       if (other.classname != "corpse")
-       if (other.classname != "body")
-       if (other.classname != "gib")
-       if (other.classname != "missile")
-       if (other.classname != "rocket")
-       if (other.classname != "casing")
-       if (other.classname != "grenade")
-       if (other.classname != "plasma")
-       if (other.classname != "plasma_prim")
-       if (other.classname != "plasma_chain")
-       if (other.classname != "droppedweapon")
-       if (other.classname != "nexball_basketball")
-       if (other.classname != "nexball_football")
-               return;
-
-       if (other.deadflag && other.iscreature)
+       if (!isPushable(other))
                return;
 
        EXACTTRIGGER_TOUCH;
@@ -1292,24 +1415,7 @@ void trigger_impulse_touch2()
        if (self.active != ACTIVE_ACTIVE) 
                return;
 
-       // FIXME: Better checking for what to push and not.
-       if not(other.iscreature)
-       if (other.classname != "corpse")
-       if (other.classname != "body")
-       if (other.classname != "gib")
-       if (other.classname != "missile")
-       if (other.classname != "rocket")
-       if (other.classname != "casing")
-       if (other.classname != "grenade")
-       if (other.classname != "plasma")
-       if (other.classname != "plasma_prim")
-       if (other.classname != "plasma_chain")
-       if (other.classname != "droppedweapon")
-       if (other.classname != "nexball_basketball")
-       if (other.classname != "nexball_football")
-               return;
-
-       if (other.deadflag && other.iscreature)
+       if (!isPushable(other))
                return;
 
        EXACTTRIGGER_TOUCH;
@@ -1333,24 +1439,7 @@ void trigger_impulse_touch3()
        if (self.active != ACTIVE_ACTIVE) 
                return;
 
-       // FIXME: Better checking for what to push and not.
-       if not(other.iscreature)
-       if (other.classname != "corpse")
-       if (other.classname != "body")
-       if (other.classname != "gib")
-       if (other.classname != "missile")
-       if (other.classname != "rocket")
-       if (other.classname != "casing")
-       if (other.classname != "grenade")
-       if (other.classname != "plasma")
-       if (other.classname != "plasma_prim")
-       if (other.classname != "plasma_chain")
-       if (other.classname != "droppedweapon")
-       if (other.classname != "nexball_basketball")
-       if (other.classname != "nexball_football")
-               return;
-
-       if (other.deadflag && other.iscreature)
+       if (!isPushable(other))
                return;
 
        EXACTTRIGGER_TOUCH;
@@ -1400,7 +1489,7 @@ void spawnfunc_trigger_impulse()
        EXACTTRIGGER_INIT;
     if(self.radius)
     {
-        if(!self.strength) self.strength = 2000 * cvar("g_triggerimpulse_radial_multiplier");
+        if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
         setorigin(self, self.origin);
         setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
         self.touch = trigger_impulse_touch3;
@@ -1409,13 +1498,13 @@ void spawnfunc_trigger_impulse()
     {
         if(self.target)
         {
-            if(!self.strength) self.strength = 950 * cvar("g_triggerimpulse_directional_multiplier");
+            if(!self.strength) self.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
             self.touch = trigger_impulse_touch1;
         }
         else
         {
             if(!self.strength) self.strength = 0.9;
-                       self.strength = pow(self.strength, cvar("g_triggerimpulse_accel_power")) * cvar("g_triggerimpulse_accel_multiplier");
+                       self.strength = pow(self.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
             self.touch = trigger_impulse_touch2;
         }
     }
@@ -1599,6 +1688,7 @@ void follow_init()
                        attach_sameorigin(dst, src, self.message);
                }
 
+               dst.solid = SOLID_NOT; // solid doesn't work with attachment
                remove(self);
        }
        else